blob: 821b48f77e4bc68cb08fc2a9614a609fc95e48c4 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000069#define DUMP_CONTENT_MODEL
70
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000071#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000104 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000105static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000107#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000108static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000109 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000110#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111
Daniel Veillard4255d502002-04-16 15:50:10 +0000112#define IS_SCHEMA(node, type) \
113 ((node != NULL) && (node->ns != NULL) && \
114 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
115 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
116
Daniel Veillardc0826a72004-08-10 14:17:33 +0000117#define FREE_AND_NULL(str) \
118 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000119 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120 str = NULL; \
121 }
122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000123#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000124 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
125 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000126
127#define IS_COMPLEX_TYPE(item) \
128 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
129 (item->builtInType == XML_SCHEMAS_ANYTYPE))
130
131#define IS_SIMPLE_TYPE(item) \
132 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
133 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000134 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000136#define IS_ANY_SIMPLE_TYPE(item) \
137 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000138 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000139
140#define IS_NOT_TYPEFIXED(item) \
141 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
142 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
143
144#define HAS_COMPLEX_CONTENT(item) \
145 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
146 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
147 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
148
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000149#define HAS_SIMPLE_CONTENT(item) \
150 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
151 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
152
153#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
154
155#define IS_PARTICLE_EMPTIABLE(item) \
156 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000158#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000160#define GET_LIST_ITEM_TYPE(item) item->subtypes
161
162#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
163#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
164#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000166#define IS_MODEL_GROUP(item) \
167 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
168 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
169 (item->type == XML_SCHEMA_TYPE_ALL))
170
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000171#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
172
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000173#define ELEM_TYPE(item) item->subtypes
174
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000175#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000177#define SUBST_GROUP_AFF(item) item->refDecl
178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000179#if 0
180#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
181#endif
182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000183#define SUBSET_RESTRICTION 1<<0
184#define SUBSET_EXTENSION 1<<1
185#define SUBSET_SUBSTITUTION 1<<2
186#define SUBSET_LIST 1<<3
187#define SUBSET_UNION 1<<4
188
Daniel Veillard4255d502002-04-16 15:50:10 +0000189#define XML_SCHEMAS_PARSE_ERROR 1
190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000193typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
194typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000199
200typedef struct _xmlSchemaItemList xmlSchemaItemList;
201typedef xmlSchemaItemList *xmlSchemaItemListPtr;
202
203struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000204 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 int nbItems; /* used for dynamic addition of schemata */
206 int sizeItems; /* used for dynamic addition of schemata */
207};
208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000209typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
210typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
211struct _xmlSchemaAbstractCtxt {
212 int type;
213};
214
215#define XML_SCHEMA_CTXT_PARSER 1
216#define XML_SCHEMA_CTXT_VALIDATOR 2
217
Daniel Veillard4255d502002-04-16 15:50:10 +0000218struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000219 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 void *userData; /* user specific data block */
221 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
222 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000223 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000227 xmlSchemaPtr topschema; /* The main schema */
228 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000231 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 int counter;
233
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000234 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000236 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 const char *buffer;
239 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241 /*
242 * Used to build complex element content models
243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245 xmlAutomataStatePtr start;
246 xmlAutomataStatePtr end;
247 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000248
249 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000250 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000251 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
252 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 xmlSchemaAssemblePtr assemble;
254 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000256 const xmlChar **localImports; /* list of locally imported namespaces */
257 int sizeLocalImports;
258 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000259 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000260 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000261};
262
Daniel Veillard4255d502002-04-16 15:50:10 +0000263#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000267#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
269#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000270#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000271#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
273#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
274#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
275#define XML_SCHEMAS_ATTR_WILD_SKIP 13
276#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
277#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
278#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
279#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281/**
282 * xmlSchemaBasicItem:
283 *
284 * The abstract base type for schema components.
285 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000286typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
287typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
288struct _xmlSchemaBasicItem {
289 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000290};
291
292/**
293 * xmlSchemaAnnotItem:
294 *
295 * The abstract base type for annotated schema components.
296 * (Extends xmlSchemaBasicItem)
297 */
298typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
299typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
300struct _xmlSchemaAnnotItem {
301 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000302 xmlSchemaAnnotPtr annot;
303};
304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000305/**
306 * xmlSchemaTreeItem:
307 *
308 * The abstract base type for tree-like structured schema components.
309 * (Extends xmlSchemaAnnotItem)
310 */
311typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
312typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
313struct _xmlSchemaTreeItem {
314 xmlSchemaTypeType type;
315 xmlSchemaAnnotPtr annot;
316 xmlSchemaTreeItemPtr next;
317 xmlSchemaTreeItemPtr children;
318};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000320/**
321 * xmlSchemaQNameRef:
322 *
323 * A component reference item (not a schema component)
324 * (Extends xmlSchemaBasicItem)
325 */
326typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
327typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
328struct _xmlSchemaQNameRef {
329 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000331 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000332 const xmlChar *name;
333 const xmlChar *targetNamespace;
334};
335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000336/**
337 * xmlSchemaParticle:
338 *
339 * A particle component.
340 * (Extends xmlSchemaTreeItem)
341 */
342typedef struct _xmlSchemaParticle xmlSchemaParticle;
343typedef xmlSchemaParticle *xmlSchemaParticlePtr;
344struct _xmlSchemaParticle {
345 xmlSchemaTypeType type;
346 xmlSchemaAnnotPtr annot;
347 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
348 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
349 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000350 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351 xmlNodePtr node;
352};
353
354/**
355 * xmlSchemaModelGroup:
356 *
357 * A model group component.
358 * (Extends xmlSchemaTreeItem)
359 */
360typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next; /* not used */
366 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
367 xmlNodePtr node;
368};
369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000370#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000371/**
372 * xmlSchemaModelGroupDef:
373 *
374 * A model group definition component.
375 * (Extends xmlSchemaTreeItem)
376 */
377typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
378typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
379struct _xmlSchemaModelGroupDef {
380 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
381 xmlSchemaAnnotPtr annot;
382 xmlSchemaTreeItemPtr next; /* not used */
383 xmlSchemaTreeItemPtr children; /* the "model group" */
384 const xmlChar *name;
385 const xmlChar *targetNamespace;
386 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000387 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388};
389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390typedef struct _xmlSchemaIDC xmlSchemaIDC;
391typedef xmlSchemaIDC *xmlSchemaIDCPtr;
392
393/**
394 * xmlSchemaIDCSelect:
395 *
396 * The identity-constraint "field" and "selector" item, holding the
397 * XPath expression.
398 */
399typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
400typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000401struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402 xmlSchemaIDCSelectPtr next;
403 xmlSchemaIDCPtr idc;
404 int index; /* an index position if significant for IDC key-sequences */
405 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000406 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000407};
408
409/**
410 * xmlSchemaIDC:
411 *
412 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000413 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000414 */
415
416struct _xmlSchemaIDC {
417 xmlSchemaTypeType type;
418 xmlSchemaAnnotPtr annot;
419 xmlSchemaIDCPtr next;
420 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 const xmlChar *targetNamespace;
423 xmlSchemaIDCSelectPtr selector;
424 xmlSchemaIDCSelectPtr fields;
425 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000426 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000427};
428
429/**
430 * xmlSchemaIDCAug:
431 *
432 * The augmented IDC information used for validation.
433 */
434typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
435typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
436struct _xmlSchemaIDCAug {
437 xmlSchemaIDCAugPtr next; /* next in a list */
438 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000439 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000440 tables need to be bubbled upwards */
441};
442
443/**
444 * xmlSchemaPSVIIDCKeySequence:
445 *
446 * The key sequence of a node table item.
447 */
448typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
449typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
450struct _xmlSchemaPSVIIDCKey {
451 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000452 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453};
454
455/**
456 * xmlSchemaPSVIIDCNode:
457 *
458 * The node table item of a node table.
459 */
460typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
461typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
462struct _xmlSchemaPSVIIDCNode {
463 xmlNodePtr node;
464 xmlSchemaPSVIIDCKeyPtr *keys;
465};
466
467/**
468 * xmlSchemaPSVIIDCBinding:
469 *
470 * The identity-constraint binding item of the [identity-constraint table].
471 */
472typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
473typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
474struct _xmlSchemaPSVIIDCBinding {
475 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
476 xmlSchemaIDCPtr definition; /* the IDC definition */
477 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
478 int nbNodes; /* number of entries in the node table */
479 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000480 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 table */
482 /* int nbKeys; number of keys in each key-sequence */
483};
484
485#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
486#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
487
488#define XPATH_STATE_OBJ_MATCHES -2
489#define XPATH_STATE_OBJ_BLOCKED -3
490
491typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
492typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
493
494/**
495 * xmlSchemaIDCStateObj:
496 *
497 * The state object used to evaluate XPath expressions.
498 */
499typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
500typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
501struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000502 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000504 int depth; /* depth of creation */
505 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 int nbHistory;
507 int sizeHistory;
508 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
509 matcher */
510 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000511 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000512};
513
514#define IDC_MATCHER 0
515
516/**
517 * xmlSchemaIDCMatcher:
518 *
519 * Used to IDC selectors (and fields) successively.
520 */
521struct _xmlSchemaIDCMatcher {
522 int type;
523 int depth; /* the tree depth at creation time */
524 xmlSchemaIDCMatcherPtr next; /* next in the list */
525 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
526 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
527 elements */
528 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 int targetDepth;
530};
531
532/*
533* Element info flags.
534*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
536#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
537#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
538#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
539
540#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
541#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
542#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
543
544#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
545#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
546#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
547#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548
549/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000550 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 *
552 * Holds information of an element node.
553 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000554struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000557 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 const xmlChar *nsName;
559 const xmlChar *value;
560 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000562 int flags; /* combination of node info flags */
563 int valNeeded;
564 int normVal;
565
566 xmlSchemaElementPtr decl; /* the element/attribute declaration */
567 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
569 for the scope element*/
570 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
571 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000572 xmlRegExecCtxtPtr regexCtxt;
573
574 const xmlChar **nsBindings; /* Namespace bindings on this element */
575 int nbNsBindings;
576 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000577};
578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000579/*
580* @metaType values of xmlSchemaAttrInfo.
581*/
582#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
584#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
585#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
586#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
589typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
590struct _xmlSchemaAttrInfo {
591 xmlNodePtr node;
592 int nodeType;
593 const xmlChar *localName;
594 const xmlChar *nsName;
595 const xmlChar *value;
596 xmlSchemaValPtr val; /* the pre-computed value if any */
597 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
598 int flags; /* combination of node info flags */
599
600 xmlSchemaAttributePtr decl; /* the attribute declaration */
601 xmlSchemaAttributePtr use; /* the attribute use */
602 int state;
603 int metaType;
604 const xmlChar *vcValue; /* the value constraint value */
605 xmlSchemaNodeInfoPtr parent;
606};
607
608
609#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000610/**
611 * xmlSchemaValidCtxt:
612 *
613 * A Schemas validation context
614 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000615struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *userData; /* user specific data block */
618 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000619 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000621
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 xmlSchemaPtr schema; /* The schema in use */
623 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 xmlCharEncoding enc;
626 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000627 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000629
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 int err;
631 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000632
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000633 xmlNodePtr node;
634 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000635 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637 xmlRegExecCtxtPtr regexp;
638 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000639
Daniel Veillardc0826a72004-08-10 14:17:33 +0000640 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000641 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000642 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000643 xmlSchemaParserCtxtPtr pctxt;
644 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000647 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000649 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
652
653 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
654 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000655
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
657 int nbIdcNodes;
658 int sizeIdcNodes;
659
660 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
661 int nbIdcKeys;
662 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000663
664 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000665
666 xmlDictPtr dict;
667
Daniel Veillard39e5c892005-07-03 22:48:50 +0000668#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000670#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671
672 xmlSchemaAttrInfoPtr *attrInfos;
673 int nbAttrInfos;
674 int sizeAttrInfos;
675
676 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000677};
678
Daniel Veillard1d913862003-11-21 00:28:39 +0000679/*
680 * These are the entries in the schemas importSchemas hash table
681 */
682typedef struct _xmlSchemaImport xmlSchemaImport;
683typedef xmlSchemaImport *xmlSchemaImportPtr;
684struct _xmlSchemaImport {
685 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000686 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000687 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000688 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000689};
Daniel Veillard4255d502002-04-16 15:50:10 +0000690
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000691/*
692 * These are the entries associated to includes in a schemas
693 */
694typedef struct _xmlSchemaInclude xmlSchemaInclude;
695typedef xmlSchemaInclude *xmlSchemaIncludePtr;
696struct _xmlSchemaInclude {
697 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698 const xmlChar *schemaLocation;
699 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000700 const xmlChar *origTargetNamespace;
701 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000702};
703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000704/**
705 * xmlSchemaSubstGroup:
706 *
707 *
708 */
709typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
710typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
711struct _xmlSchemaSubstGroup {
712 xmlSchemaElementPtr head;
713 xmlSchemaItemListPtr members;
714};
715
Daniel Veillard4255d502002-04-16 15:50:10 +0000716/************************************************************************
717 * *
718 * Some predeclarations *
719 * *
720 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000722static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
723 xmlSchemaPtr schema,
724 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725static void
726xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
727 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000728static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000729xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
730static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000731xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
732 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000733static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000734xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
735 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000736static void
737xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000738static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000739xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740static xmlSchemaTreeItemPtr
741xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
742 xmlNodePtr node, xmlSchemaTypeType type,
743 int withParticle);
744static const xmlChar *
745xmlSchemaCompTypeToString(xmlSchemaTypeType type);
746static xmlSchemaTypeLinkPtr
747xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748static void
749xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
750 const char *funcName,
751 const char *message);
752static int
753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
754 xmlSchemaTypePtr baseType,
755 int subset);
756static void
757xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
758 xmlSchemaParserCtxtPtr ctxt,
759 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000760
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761/************************************************************************
762 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000763 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 * *
765 ************************************************************************/
766
767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000768 * xmlSchemaCompTypeToString:
769 * @type: the type of the schema item
770 *
771 * Returns the component name of a schema item.
772 */
773static const xmlChar *
774xmlSchemaCompTypeToString(xmlSchemaTypeType type)
775{
776 switch (type) {
777 case XML_SCHEMA_TYPE_SIMPLE:
778 return(BAD_CAST "simple type definition");
779 case XML_SCHEMA_TYPE_COMPLEX:
780 return(BAD_CAST "complex type definition");
781 case XML_SCHEMA_TYPE_ELEMENT:
782 return(BAD_CAST "element declaration");
783 case XML_SCHEMA_TYPE_ATTRIBUTE:
784 return(BAD_CAST "attribute declaration");
785 case XML_SCHEMA_TYPE_GROUP:
786 return(BAD_CAST "model group definition");
787 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
788 return(BAD_CAST "attribute group definition");
789 case XML_SCHEMA_TYPE_NOTATION:
790 return(BAD_CAST "notation declaration");
791 case XML_SCHEMA_TYPE_SEQUENCE:
792 return(BAD_CAST "model group (sequence)");
793 case XML_SCHEMA_TYPE_CHOICE:
794 return(BAD_CAST "model group (choice)");
795 case XML_SCHEMA_TYPE_ALL:
796 return(BAD_CAST "model group (all)");
797 case XML_SCHEMA_TYPE_PARTICLE:
798 return(BAD_CAST "particle");
799 default:
800 return(BAD_CAST "Not a schema component");
801 }
802}
803
804/**
805 * xmlSchemaGetComponentNode:
806 * @item: a schema component
807 *
808 * Returns node associated with the schema component.
809 * NOTE that such a node need not be available; plus, a component's
810 * node need not to reflect the component directly, since there is no
811 * one-to-one relationship between the XML Schema representation and
812 * the component representation.
813 */
814static xmlNodePtr
815xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
816{
817 switch (item->type) {
818 case XML_SCHEMA_TYPE_ELEMENT:
819 return (((xmlSchemaElementPtr) item)->node);
820 case XML_SCHEMA_TYPE_ATTRIBUTE:
821 return (((xmlSchemaAttributePtr) item)->node);
822 case XML_SCHEMA_TYPE_COMPLEX:
823 case XML_SCHEMA_TYPE_SIMPLE:
824 return (((xmlSchemaTypePtr) item)->node);
825 case XML_SCHEMA_TYPE_ANY:
826 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
827 return (((xmlSchemaWildcardPtr) item)->node);
828 case XML_SCHEMA_TYPE_PARTICLE:
829 return (((xmlSchemaParticlePtr) item)->node);
830 case XML_SCHEMA_TYPE_SEQUENCE:
831 case XML_SCHEMA_TYPE_CHOICE:
832 case XML_SCHEMA_TYPE_ALL:
833 return (((xmlSchemaModelGroupPtr) item)->node);
834 case XML_SCHEMA_TYPE_GROUP:
835 return (((xmlSchemaModelGroupDefPtr) item)->node);
836 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
837 return (((xmlSchemaAttributeGroupPtr) item)->node);
838 case XML_SCHEMA_TYPE_IDC_UNIQUE:
839 case XML_SCHEMA_TYPE_IDC_KEY:
840 case XML_SCHEMA_TYPE_IDC_KEYREF:
841 return (((xmlSchemaIDCPtr) item)->node);
842 default:
843 return (NULL);
844 }
845}
846
847#if 0
848/**
849 * xmlSchemaGetNextComponent:
850 * @item: a schema component
851 *
852 * Returns the next sibling of the schema component.
853 */
854static xmlSchemaBasicItemPtr
855xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
856{
857 switch (item->type) {
858 case XML_SCHEMA_TYPE_ELEMENT:
859 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
860 case XML_SCHEMA_TYPE_ATTRIBUTE:
861 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
862 case XML_SCHEMA_TYPE_COMPLEX:
863 case XML_SCHEMA_TYPE_SIMPLE:
864 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
865 case XML_SCHEMA_TYPE_ANY:
866 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
867 return (NULL);
868 case XML_SCHEMA_TYPE_PARTICLE:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
870 case XML_SCHEMA_TYPE_SEQUENCE:
871 case XML_SCHEMA_TYPE_CHOICE:
872 case XML_SCHEMA_TYPE_ALL:
873 return (NULL);
874 case XML_SCHEMA_TYPE_GROUP:
875 return (NULL);
876 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
877 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
878 case XML_SCHEMA_TYPE_IDC_UNIQUE:
879 case XML_SCHEMA_TYPE_IDC_KEY:
880 case XML_SCHEMA_TYPE_IDC_KEYREF:
881 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
882 default:
883 return (NULL);
884 }
885}
886#endif
887
888/**
889 * xmlSchemaGetAttrName:
890 * @attr: the attribute declaration/use
891 *
892 * Returns the name of the attribute; if the attribute
893 * is a reference, the name of the referenced global type will be returned.
894 */
895static const xmlChar *
896xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
897{
898 if (attr->ref != NULL)
899 return(attr->ref);
900 else
901 return(attr->name);
902}
903
904/**
905 * xmlSchemaGetAttrTargetNsURI:
906 * @type: the type (element or attribute)
907 *
908 * Returns the target namespace URI of the type; if the type is a reference,
909 * the target namespace of the referenced type will be returned.
910 */
911static const xmlChar *
912xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
913{
914 if (attr->ref != NULL)
915 return (attr->refNs);
916 else
917 return(attr->targetNamespace);
918}
919
920/**
921 * xmlSchemaFormatQName:
922 * @buf: the string buffer
923 * @namespaceName: the namespace name
924 * @localName: the local name
925 *
926 * Returns the given QName in the format "{namespaceName}localName" or
927 * just "localName" if @namespaceName is NULL.
928 *
929 * Returns the localName if @namespaceName is NULL, a formatted
930 * string otherwise.
931 */
932static const xmlChar*
933xmlSchemaFormatQName(xmlChar **buf,
934 const xmlChar *namespaceName,
935 const xmlChar *localName)
936{
937 FREE_AND_NULL(*buf)
938 if (namespaceName == NULL)
939 return(localName);
940
941 *buf = xmlStrdup(BAD_CAST "{");
942 *buf = xmlStrcat(*buf, namespaceName);
943 *buf = xmlStrcat(*buf, BAD_CAST "}");
944 *buf = xmlStrcat(*buf, localName);
945
946 return ((const xmlChar *) *buf);
947}
948
949static const xmlChar*
950xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
951{
952 if (ns != NULL)
953 return (xmlSchemaFormatQName(buf, ns->href, localName));
954 else
955 return (xmlSchemaFormatQName(buf, NULL, localName));
956}
957
958static const xmlChar *
959xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
960{
961 switch (item->type) {
962 case XML_SCHEMA_TYPE_ELEMENT:
963 return (((xmlSchemaElementPtr) item)->name);
964 case XML_SCHEMA_TYPE_ATTRIBUTE:
965 return (((xmlSchemaAttributePtr) item)->name);
966 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
967 return (((xmlSchemaAttributeGroupPtr) item)->name);
968 case XML_SCHEMA_TYPE_BASIC:
969 case XML_SCHEMA_TYPE_SIMPLE:
970 case XML_SCHEMA_TYPE_COMPLEX:
971 return (((xmlSchemaTypePtr) item)->name);
972 case XML_SCHEMA_TYPE_GROUP:
973 return (((xmlSchemaModelGroupDefPtr) item)->name);
974 case XML_SCHEMA_TYPE_IDC_KEY:
975 case XML_SCHEMA_TYPE_IDC_UNIQUE:
976 case XML_SCHEMA_TYPE_IDC_KEYREF:
977 return (((xmlSchemaIDCPtr) item)->name);
978 default:
979 /*
980 * Other components cannot have names.
981 */
982 break;
983 }
984 return (NULL);
985}
986
987static const xmlChar *
988xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
989{
990 switch (item->type) {
991 case XML_SCHEMA_TYPE_ELEMENT:
992 return (((xmlSchemaElementPtr) item)->targetNamespace);
993 case XML_SCHEMA_TYPE_ATTRIBUTE:
994 return (((xmlSchemaAttributePtr) item)->targetNamespace);
995 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
996 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
997 case XML_SCHEMA_TYPE_BASIC:
998 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
999 case XML_SCHEMA_TYPE_SIMPLE:
1000 case XML_SCHEMA_TYPE_COMPLEX:
1001 return (((xmlSchemaTypePtr) item)->targetNamespace);
1002 case XML_SCHEMA_TYPE_GROUP:
1003 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1004 case XML_SCHEMA_TYPE_IDC_KEY:
1005 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1006 case XML_SCHEMA_TYPE_IDC_KEYREF:
1007 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1008 default:
1009 /*
1010 * Other components cannot have names.
1011 */
1012 break;
1013 }
1014 return (NULL);
1015}
1016
1017static const xmlChar*
1018xmlSchemaGetComponentQName(xmlChar **buf,
1019 void *item)
1020{
1021 return (xmlSchemaFormatQName(buf,
1022 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1023 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1024}
1025
1026/**
1027 * xmlSchemaWildcardPCToString:
1028 * @pc: the type of processContents
1029 *
1030 * Returns a string representation of the type of
1031 * processContents.
1032 */
1033static const xmlChar *
1034xmlSchemaWildcardPCToString(int pc)
1035{
1036 switch (pc) {
1037 case XML_SCHEMAS_ANY_SKIP:
1038 return (BAD_CAST "skip");
1039 case XML_SCHEMAS_ANY_LAX:
1040 return (BAD_CAST "lax");
1041 case XML_SCHEMAS_ANY_STRICT:
1042 return (BAD_CAST "strict");
1043 default:
1044 return (BAD_CAST "invalid process contents");
1045 }
1046}
1047
1048/**
1049 * xmlSchemaGetCanonValueWhtspExt:
1050 * @val: the precomputed value
1051 * @retValue: the returned value
1052 * @ws: the whitespace type of the value
1053 *
1054 * Get a the cononical representation of the value.
1055 * The caller has to free the returned retValue.
1056 *
1057 * Returns 0 if the value could be built and -1 in case of
1058 * API errors or if the value type is not supported yet.
1059 */
1060static int
1061xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1062 xmlSchemaWhitespaceValueType ws,
1063 xmlChar **retValue)
1064{
1065 int list;
1066 xmlSchemaValType valType;
1067 const xmlChar *value, *value2 = NULL;
1068
1069
1070 if ((retValue == NULL) || (val == NULL))
1071 return (-1);
1072 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1073 *retValue = NULL;
1074 do {
1075 value = NULL;
1076 valType = xmlSchemaGetValType(val);
1077 switch (valType) {
1078 case XML_SCHEMAS_STRING:
1079 case XML_SCHEMAS_NORMSTRING:
1080 case XML_SCHEMAS_ANYSIMPLETYPE:
1081 value = xmlSchemaValueGetAsString(val);
1082 if (value != NULL) {
1083 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1084 value2 = xmlSchemaCollapseString(value);
1085 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1086 value2 = xmlSchemaWhiteSpaceReplace(value);
1087 if (value2 != NULL)
1088 value = value2;
1089 }
1090 break;
1091 default:
1092 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1093 if (value2 != NULL)
1094 xmlFree((xmlChar *) value2);
1095 goto internal_error;
1096 }
1097 value = value2;
1098 }
1099 if (*retValue == NULL)
1100 if (value == NULL) {
1101 if (! list)
1102 *retValue = xmlStrdup(BAD_CAST "");
1103 } else
1104 *retValue = xmlStrdup(value);
1105 else if (value != NULL) {
1106 /* List. */
1107 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1108 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1109 }
1110 FREE_AND_NULL(value2)
1111 val = xmlSchemaValueGetNext(val);
1112 } while (val != NULL);
1113
1114 return (0);
1115internal_error:
1116 if (*retValue != NULL)
1117 xmlFree((xmlChar *) (*retValue));
1118 if (value2 != NULL)
1119 xmlFree((xmlChar *) value2);
1120 return (-1);
1121}
1122
1123/**
1124 * xmlSchemaFormatItemForReport:
1125 * @buf: the string buffer
1126 * @itemDes: the designation of the item
1127 * @itemName: the name of the item
1128 * @item: the item as an object
1129 * @itemNode: the node of the item
1130 * @local: the local name
1131 * @parsing: if the function is used during the parse
1132 *
1133 * Returns a representation of the given item used
1134 * for error reports.
1135 *
1136 * The following order is used to build the resulting
1137 * designation if the arguments are not NULL:
1138 * 1a. If itemDes not NULL -> itemDes
1139 * 1b. If (itemDes not NULL) and (itemName not NULL)
1140 * -> itemDes + itemName
1141 * 2. If the preceding was NULL and (item not NULL) -> item
1142 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1143 *
1144 * If the itemNode is an attribute node, the name of the attribute
1145 * will be appended to the result.
1146 *
1147 * Returns the formatted string and sets @buf to the resulting value.
1148 */
1149static xmlChar*
1150xmlSchemaFormatItemForReport(xmlChar **buf,
1151 const xmlChar *itemDes,
1152 xmlSchemaTypePtr item,
1153 xmlNodePtr itemNode)
1154{
1155 xmlChar *str = NULL;
1156 int named = 1;
1157
1158 if (*buf != NULL) {
1159 xmlFree(*buf);
1160 *buf = NULL;
1161 }
1162
1163 if (itemDes != NULL) {
1164 *buf = xmlStrdup(itemDes);
1165 } else if (item != NULL) {
1166 switch (item->type) {
1167 case XML_SCHEMA_TYPE_BASIC:
1168 if (VARIETY_ATOMIC(item))
1169 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1170 else if (VARIETY_LIST(item))
1171 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1172 else if (VARIETY_UNION(item))
1173 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1174 else
1175 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1176 *buf = xmlStrcat(*buf, item->name);
1177 *buf = xmlStrcat(*buf, BAD_CAST "'");
1178 break;
1179 case XML_SCHEMA_TYPE_SIMPLE:
1180 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1181 *buf = xmlStrdup(BAD_CAST"");
1182 } else {
1183 *buf = xmlStrdup(BAD_CAST "local ");
1184 }
1185 if (VARIETY_ATOMIC(item))
1186 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1187 else if (VARIETY_LIST(item))
1188 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1189 else if (VARIETY_UNION(item))
1190 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1191 else
1192 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1193 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1194 *buf = xmlStrcat(*buf, BAD_CAST " '");
1195 *buf = xmlStrcat(*buf, item->name);
1196 *buf = xmlStrcat(*buf, BAD_CAST "'");
1197 }
1198 break;
1199 case XML_SCHEMA_TYPE_COMPLEX:
1200 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1201 *buf = xmlStrdup(BAD_CAST "");
1202 else
1203 *buf = xmlStrdup(BAD_CAST "local ");
1204 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1205 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1206 *buf = xmlStrcat(*buf, BAD_CAST " '");
1207 *buf = xmlStrcat(*buf, item->name);
1208 *buf = xmlStrcat(*buf, BAD_CAST "'");
1209 }
1210 break;
1211 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1212 xmlSchemaAttributePtr attr;
1213
1214 attr = (xmlSchemaAttributePtr) item;
1215 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1216 (attr->ref == NULL)) {
1217 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1218 *buf = xmlStrcat(*buf, BAD_CAST " '");
1219 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1220 attr->targetNamespace, attr->name));
1221 FREE_AND_NULL(str)
1222 *buf = xmlStrcat(*buf, BAD_CAST "'");
1223 } else {
1224 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1225 *buf = xmlStrcat(*buf, BAD_CAST " '");
1226 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1227 attr->refNs, attr->ref));
1228 FREE_AND_NULL(str)
1229 *buf = xmlStrcat(*buf, BAD_CAST "'");
1230 }
1231 }
1232 break;
1233 case XML_SCHEMA_TYPE_ELEMENT: {
1234 xmlSchemaElementPtr elem;
1235
1236 elem = (xmlSchemaElementPtr) item;
1237 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1238 (elem->ref == NULL)) {
1239 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1240 *buf = xmlStrcat(*buf, BAD_CAST " '");
1241 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1242 elem->targetNamespace, elem->name));
1243 *buf = xmlStrcat(*buf, BAD_CAST "'");
1244 }
1245 }
1246 break;
1247 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1248 case XML_SCHEMA_TYPE_IDC_KEY:
1249 case XML_SCHEMA_TYPE_IDC_KEYREF:
1250 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1251 *buf = xmlStrdup(BAD_CAST "unique '");
1252 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1253 *buf = xmlStrdup(BAD_CAST "key '");
1254 else
1255 *buf = xmlStrdup(BAD_CAST "keyRef '");
1256 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1257 *buf = xmlStrcat(*buf, BAD_CAST "'");
1258 break;
1259 case XML_SCHEMA_TYPE_ANY:
1260 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1261 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1262 ((xmlSchemaWildcardPtr) item)->processContents));
1263 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1264 break;
1265 case XML_SCHEMA_FACET_MININCLUSIVE:
1266 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1267 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1268 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1269 case XML_SCHEMA_FACET_TOTALDIGITS:
1270 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1271 case XML_SCHEMA_FACET_PATTERN:
1272 case XML_SCHEMA_FACET_ENUMERATION:
1273 case XML_SCHEMA_FACET_WHITESPACE:
1274 case XML_SCHEMA_FACET_LENGTH:
1275 case XML_SCHEMA_FACET_MAXLENGTH:
1276 case XML_SCHEMA_FACET_MINLENGTH:
1277 *buf = xmlStrdup(BAD_CAST "facet '");
1278 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1279 *buf = xmlStrcat(*buf, BAD_CAST "'");
1280 break;
1281 case XML_SCHEMA_TYPE_NOTATION:
1282 *buf = xmlStrdup(BAD_CAST "notation");
1283 break;
1284 case XML_SCHEMA_TYPE_GROUP: {
1285 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1286 *buf = xmlStrcat(*buf, BAD_CAST " '");
1287 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1288 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1289 ((xmlSchemaModelGroupDefPtr) item)->name));
1290 *buf = xmlStrcat(*buf, BAD_CAST "'");
1291 FREE_AND_NULL(str)
1292 }
1293 break;
1294 case XML_SCHEMA_TYPE_SEQUENCE:
1295 case XML_SCHEMA_TYPE_CHOICE:
1296 case XML_SCHEMA_TYPE_ALL:
1297 case XML_SCHEMA_TYPE_PARTICLE:
1298 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1299 break;
1300 default:
1301 named = 0;
1302 }
1303 } else
1304 named = 0;
1305
1306 if ((named == 0) && (itemNode != NULL)) {
1307 xmlNodePtr elem;
1308
1309 if (itemNode->type == XML_ATTRIBUTE_NODE)
1310 elem = itemNode->parent;
1311 else
1312 elem = itemNode;
1313 *buf = xmlStrdup(BAD_CAST "Element '");
1314 if (elem->ns != NULL) {
1315 *buf = xmlStrcat(*buf,
1316 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1317 FREE_AND_NULL(str)
1318 } else
1319 *buf = xmlStrcat(*buf, elem->name);
1320 *buf = xmlStrcat(*buf, BAD_CAST "'");
1321
1322 }
1323 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1324 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1325 if (itemNode->ns != NULL) {
1326 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1327 itemNode->ns->href, itemNode->name));
1328 FREE_AND_NULL(str)
1329 } else
1330 *buf = xmlStrcat(*buf, itemNode->name);
1331 *buf = xmlStrcat(*buf, BAD_CAST "'");
1332 }
1333 FREE_AND_NULL(str)
1334
1335 return (*buf);
1336}
1337
1338/**
1339 * xmlSchemaFormatFacetEnumSet:
1340 * @buf: the string buffer
1341 * @type: the type holding the enumeration facets
1342 *
1343 * Builds a string consisting of all enumeration elements.
1344 *
1345 * Returns a string of all enumeration elements.
1346 */
1347static const xmlChar *
1348xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1349 xmlChar **buf, xmlSchemaTypePtr type)
1350{
1351 xmlSchemaFacetPtr facet;
1352 xmlSchemaWhitespaceValueType ws;
1353 xmlChar *value = NULL;
1354 int res;
1355
1356 if (*buf != NULL)
1357 xmlFree(*buf);
1358 *buf = NULL;
1359
1360 do {
1361 /*
1362 * Use the whitespace type of the base type.
1363 */
1364 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1365 for (facet = type->facets; facet != NULL; facet = facet->next) {
1366 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1367 continue;
1368 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1369 ws, &value);
1370 if (res == -1) {
1371 xmlSchemaInternalErr(actxt,
1372 "xmlSchemaFormatFacetEnumSet",
1373 "compute the canonical lexical representation");
1374 if (*buf != NULL)
1375 xmlFree(*buf);
1376 *buf = NULL;
1377 return (NULL);
1378 }
1379 if (*buf == NULL)
1380 *buf = xmlStrdup(BAD_CAST "'");
1381 else
1382 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1383 *buf = xmlStrcat(*buf, BAD_CAST value);
1384 *buf = xmlStrcat(*buf, BAD_CAST "'");
1385 if (value != NULL) {
1386 xmlFree((xmlChar *)value);
1387 value = NULL;
1388 }
1389 }
1390 type = type->baseType;
1391 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1392
1393 return ((const xmlChar *) *buf);
1394}
1395
1396/************************************************************************
1397 * *
1398 * Error functions *
1399 * *
1400 ************************************************************************/
1401
1402#if 0
1403static void
1404xmlSchemaErrMemory(const char *msg)
1405{
1406 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1407 msg);
1408}
1409#endif
1410
1411/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001412 * xmlSchemaPErrMemory:
1413 * @node: a context node
1414 * @extra: extra informations
1415 *
1416 * Handle an out of memory condition
1417 */
1418static void
1419xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1420 const char *extra, xmlNodePtr node)
1421{
1422 if (ctxt != NULL)
1423 ctxt->nberrors++;
1424 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1425 extra);
1426}
1427
1428/**
1429 * xmlSchemaPErr:
1430 * @ctxt: the parsing context
1431 * @node: the context node
1432 * @error: the error code
1433 * @msg: the error message
1434 * @str1: extra data
1435 * @str2: extra data
1436 *
1437 * Handle a parser error
1438 */
1439static void
1440xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1441 const char *msg, const xmlChar * str1, const xmlChar * str2)
1442{
1443 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001444 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001445 void *data = NULL;
1446
1447 if (ctxt != NULL) {
1448 ctxt->nberrors++;
1449 channel = ctxt->error;
1450 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001451 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001453 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 error, XML_ERR_ERROR, NULL, 0,
1455 (const char *) str1, (const char *) str2, NULL, 0, 0,
1456 msg, str1, str2);
1457}
1458
1459/**
1460 * xmlSchemaPErr2:
1461 * @ctxt: the parsing context
1462 * @node: the context node
1463 * @node: the current child
1464 * @error: the error code
1465 * @msg: the error message
1466 * @str1: extra data
1467 * @str2: extra data
1468 *
1469 * Handle a parser error
1470 */
1471static void
1472xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1473 xmlNodePtr child, int error,
1474 const char *msg, const xmlChar * str1, const xmlChar * str2)
1475{
1476 if (child != NULL)
1477 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1478 else
1479 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1480}
1481
Daniel Veillard01fa6152004-06-29 17:04:39 +00001482
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001483/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001484 * xmlSchemaPErrExt:
1485 * @ctxt: the parsing context
1486 * @node: the context node
1487 * @error: the error code
1488 * @strData1: extra data
1489 * @strData2: extra data
1490 * @strData3: extra data
1491 * @msg: the message
1492 * @str1: extra parameter for the message display
1493 * @str2: extra parameter for the message display
1494 * @str3: extra parameter for the message display
1495 * @str4: extra parameter for the message display
1496 * @str5: extra parameter for the message display
1497 *
1498 * Handle a parser error
1499 */
1500static void
1501xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1502 const xmlChar * strData1, const xmlChar * strData2,
1503 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1504 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1505 const xmlChar * str5)
1506{
1507
1508 xmlGenericErrorFunc channel = NULL;
1509 xmlStructuredErrorFunc schannel = NULL;
1510 void *data = NULL;
1511
1512 if (ctxt != NULL) {
1513 ctxt->nberrors++;
1514 channel = ctxt->error;
1515 data = ctxt->userData;
1516 schannel = ctxt->serror;
1517 }
1518 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1519 error, XML_ERR_ERROR, NULL, 0,
1520 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001521 (const char *) strData3, 0, 0, msg, str1, str2,
1522 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001523}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001525/************************************************************************
1526 * *
1527 * Allround error functions *
1528 * *
1529 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001530
1531/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001532 * xmlSchemaVTypeErrMemory:
1533 * @node: a context node
1534 * @extra: extra informations
1535 *
1536 * Handle an out of memory condition
1537 */
1538static void
1539xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1540 const char *extra, xmlNodePtr node)
1541{
1542 if (ctxt != NULL) {
1543 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001544 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001545 }
1546 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1547 extra);
1548}
1549
1550/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001551 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 * @ctxt: the validation context
1553 * @node: the context node
1554 * @error: the error code
1555 * @msg: the error message
1556 * @str1: extra data
1557 * @str2: extra data
1558 * @str3: extra data
1559 *
1560 * Handle a validation error
1561 */
1562static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001563xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1564 int error, xmlNodePtr node, const char *msg,
1565 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001566{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001567 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001568 xmlGenericErrorFunc channel = NULL;
1569 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571 if (ctxt != NULL) {
1572 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1573 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001574 int line = 0;
1575 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001576
1577 vctxt->nberrors++;
1578 vctxt->err = error;
1579 channel = vctxt->error;
1580 schannel = vctxt->serror;
1581 data = vctxt->userData;
1582 if ((node == NULL) && (vctxt->depth >= 0) &&
Daniel Veillard971771e2005-07-09 17:32:57 +00001583 (vctxt->inode != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001584 node = vctxt->inode->node;
Daniel Veillard971771e2005-07-09 17:32:57 +00001585 }
1586 if ((node == NULL) && (vctxt->parserCtxt != NULL) &&
1587 (vctxt->parserCtxt->input != NULL)) {
1588 file = vctxt->parserCtxt->input->filename;
1589 line = vctxt->parserCtxt->input->line;
1590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001591 __xmlRaiseError(schannel, channel, data, ctxt,
1592 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001593 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001594 (const char *) str1, (const char *) str2,
1595 (const char *) str3, 0, 0, msg, str1, str2, str3);
1596
1597 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1598 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1599
1600 pctxt->nberrors++;
1601 pctxt->err = error;
1602 channel = pctxt->error;
1603 schannel = pctxt->serror;
1604 data = pctxt->userData;
1605 __xmlRaiseError(schannel, channel, data, ctxt,
1606 node, XML_FROM_SCHEMASP,
1607 error, XML_ERR_ERROR, NULL, 0,
1608 (const char *) str1, (const char *) str2,
1609 (const char *) str3, 0, 0, msg, str1, str2, str3);
1610 } else {
1611 TODO
1612 }
1613 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001614}
1615
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001616static void
1617xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1618 int error, xmlNodePtr node, const char *msg,
1619 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001620{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001621 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001622}
1623
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001624static xmlChar *
1625xmlSchemaFormatNodeForError(xmlChar ** msg,
1626 xmlSchemaAbstractCtxtPtr actxt,
1627 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001628{
1629 xmlChar *str = NULL;
1630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001631 if (node != NULL) {
1632 /*
1633 * Work on tree nodes.
1634 */
1635 if (node->type == XML_ATTRIBUTE_NODE) {
1636 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001637
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001638 *msg = xmlStrdup(BAD_CAST "Element '");
1639 if (elem->ns != NULL)
1640 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1641 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001642 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001643 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1644 NULL, elem->name));
1645 FREE_AND_NULL(str);
1646 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1647 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1648 } else {
1649 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001650 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001651 if (node->ns != NULL)
1652 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1653 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001654 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001655 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1656 NULL, node->name));
1657 FREE_AND_NULL(str);
1658 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1659 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1660 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1661 /*
1662 * Work on node infos.
1663 */
1664 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1665 xmlSchemaNodeInfoPtr ielem =
1666 vctxt->elemInfos[vctxt->depth];
1667
1668 *msg = xmlStrdup(BAD_CAST "Element '");
1669 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1670 ielem->nsName, ielem->localName));
1671 FREE_AND_NULL(str);
1672 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1673 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1674 } else {
1675 *msg = xmlStrdup(BAD_CAST "Element '");
1676 }
1677 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1678 vctxt->inode->nsName, vctxt->inode->localName));
1679 FREE_AND_NULL(str);
1680 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1681 } else {
1682 TODO
1683 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001684 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001685 /*
1686 * VAL TODO: The output of the given schema component is currently
1687 * disabled.
1688 */
1689#if 0
1690 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1691 *msg = xmlStrcat(*msg, BAD_CAST " [");
1692 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1693 NULL, type, NULL, 0));
1694 FREE_AND_NULL(str)
1695 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001697#endif
1698 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001699}
1700
Daniel Veillardc0826a72004-08-10 14:17:33 +00001701static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001702xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1703 const char *funcName,
1704 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001705{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001706 xmlChar *msg = NULL;
1707
1708 msg = xmlStrdup(BAD_CAST "Internal error: ");
1709 msg = xmlStrcat(msg, BAD_CAST funcName);
1710 msg = xmlStrcat(msg, BAD_CAST ", ");
1711 msg = xmlStrcat(msg, BAD_CAST message);
1712 msg = xmlStrcat(msg, BAD_CAST ".\n");
1713
1714 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1715 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1716 (const char *) msg, NULL, NULL);
1717
1718 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1719 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1720 (const char *) msg, NULL, NULL);
1721
1722 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001723}
1724
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001725static void
1726xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1727 xmlParserErrors error,
1728 xmlNodePtr node,
1729 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1730 const char *message,
1731 const xmlChar *str1,
1732 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001733{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001734 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001735
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001736 xmlSchemaFormatNodeForError(&msg, actxt, node);
1737 msg = xmlStrcat(msg, (const xmlChar *) message);
1738 msg = xmlStrcat(msg, BAD_CAST ".\n");
1739 xmlSchemaErr(actxt, error, node,
1740 (const char *) msg, str1, str2);
1741 FREE_AND_NULL(msg)
1742}
1743
1744static int
1745xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1746 xmlNodePtr node)
1747{
1748 if (node != NULL)
1749 return (node->type);
1750 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1751 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1752 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1753 return (-1);
1754}
1755
1756static int
1757xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1758{
1759 switch (item->type) {
1760 case XML_SCHEMA_TYPE_COMPLEX:
1761 case XML_SCHEMA_TYPE_SIMPLE:
1762 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1763 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001764 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001765 case XML_SCHEMA_TYPE_GROUP:
1766 return (1);
1767 case XML_SCHEMA_TYPE_ELEMENT:
1768 if ( ((xmlSchemaElementPtr) item)->flags &
1769 XML_SCHEMAS_ELEM_GLOBAL)
1770 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001771 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001772 case XML_SCHEMA_TYPE_ATTRIBUTE:
1773 if ( ((xmlSchemaAttributePtr) item)->flags &
1774 XML_SCHEMAS_ATTR_GLOBAL)
1775 return(1);
1776 break;
1777 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001778 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001779 return(1);
1780 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001781 return (0);
1782}
1783
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001784static void
1785xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1786 xmlParserErrors error,
1787 xmlNodePtr node,
1788 const xmlChar *value,
1789 xmlSchemaTypePtr type,
1790 int displayValue)
1791{
1792 xmlChar *msg = NULL;
1793
1794 xmlSchemaFormatNodeForError(&msg, actxt, node);
1795
1796 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1797 XML_ATTRIBUTE_NODE))
1798 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1799 else
1800 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1801 "value of ");
1802
1803 if (! xmlSchemaIsGlobalItem(type))
1804 msg = xmlStrcat(msg, BAD_CAST "the local ");
1805 else
1806 msg = xmlStrcat(msg, BAD_CAST "the ");
1807
1808 if (VARIETY_ATOMIC(type))
1809 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1810 else if (VARIETY_LIST(type))
1811 msg = xmlStrcat(msg, BAD_CAST "list type");
1812 else if (VARIETY_UNION(type))
1813 msg = xmlStrcat(msg, BAD_CAST "union type");
1814
1815 if (xmlSchemaIsGlobalItem(type)) {
1816 xmlChar *str = NULL;
1817 msg = xmlStrcat(msg, BAD_CAST " '");
1818 if (type->builtInType != 0) {
1819 msg = xmlStrcat(msg, BAD_CAST "xs:");
1820 msg = xmlStrcat(msg, type->name);
1821 } else
1822 msg = xmlStrcat(msg,
1823 xmlSchemaFormatQName(&str,
1824 type->targetNamespace, type->name));
1825 msg = xmlStrcat(msg, BAD_CAST "'");
1826 FREE_AND_NULL(str);
1827 }
1828 msg = xmlStrcat(msg, BAD_CAST ".\n");
1829 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1830 XML_ATTRIBUTE_NODE))
1831 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1832 else
1833 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1834 FREE_AND_NULL(msg)
1835}
1836
Daniel Veillardc0826a72004-08-10 14:17:33 +00001837static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001838xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1839 xmlSchemaNodeInfoPtr ni,
1840 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001841{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001842 if (node != NULL) {
1843 if (node->ns != NULL)
1844 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1845 else
1846 return (xmlSchemaFormatQName(str, NULL, node->name));
1847 } else if (ni != NULL)
1848 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1849 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001850}
1851
Daniel Veillardc0826a72004-08-10 14:17:33 +00001852static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001853xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1854 xmlParserErrors error,
1855 xmlSchemaAttrInfoPtr ni,
1856 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001857{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001858 xmlChar *msg = NULL, *str = NULL;
1859
1860 xmlSchemaFormatNodeForError(&msg, actxt, node);
1861 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1862 xmlSchemaErr(actxt, error, node, (const char *) msg,
1863 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1864 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001865 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001866 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001867}
1868
Daniel Veillardc0826a72004-08-10 14:17:33 +00001869static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001870xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1871 xmlParserErrors error,
1872 xmlNodePtr node,
1873 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001874 const char *message,
1875 int nbval,
1876 int nbneg,
1877 xmlChar **values)
1878{
1879 xmlChar *str = NULL, *msg = NULL;
1880 xmlChar *localName, *nsName;
1881 const xmlChar *cur, *end;
1882 int i;
1883
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001884 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001885 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001886 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001887 /*
1888 * Note that is does not make sense to report that we have a
1889 * wildcard here, since the wildcard might be unfolded into
1890 * multiple transitions.
1891 */
1892 if (nbval + nbneg > 0) {
1893 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001894 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001895 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001896 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001897 nsName = NULL;
1898
1899 for (i = 0; i < nbval + nbneg; i++) {
1900 cur = values[i];
1901 /*
1902 * Get the local name.
1903 */
1904 localName = NULL;
1905
1906 end = cur;
1907 if (*end == '*') {
1908 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001909 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001910 } else {
1911 while ((*end != 0) && (*end != '|'))
1912 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001913 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001914 }
1915 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001916 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001917 /*
1918 * Skip "*|*" if they come with negated expressions, since
1919 * they represent the same negated wildcard.
1920 */
1921 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1922 /*
1923 * Get the namespace name.
1924 */
1925 cur = end;
1926 if (*end == '*') {
1927 nsName = xmlStrdup(BAD_CAST "{*}");
1928 } else {
1929 while (*end != 0)
1930 end++;
1931
1932 if (i >= nbval)
1933 nsName = xmlStrdup(BAD_CAST "{##other:");
1934 else
1935 nsName = xmlStrdup(BAD_CAST "{");
1936
1937 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1938 nsName = xmlStrcat(nsName, BAD_CAST "}");
1939 }
1940 str = xmlStrcat(str, BAD_CAST nsName);
1941 FREE_AND_NULL(nsName)
1942 } else {
1943 FREE_AND_NULL(localName);
1944 continue;
1945 }
1946 }
1947 str = xmlStrcat(str, BAD_CAST localName);
1948 FREE_AND_NULL(localName);
1949
1950 if (i < nbval + nbneg -1)
1951 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001952 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001953 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001954 msg = xmlStrcat(msg, BAD_CAST str);
1955 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001956 } else
1957 msg = xmlStrcat(msg, BAD_CAST "\n");
1958 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001959 xmlFree(msg);
1960}
1961
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001962static void
1963xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1964 xmlParserErrors error,
1965 xmlNodePtr node,
1966 const xmlChar *value,
1967 unsigned long length,
1968 xmlSchemaTypePtr type,
1969 xmlSchemaFacetPtr facet,
1970 const char *message,
1971 const xmlChar *str1,
1972 const xmlChar *str2)
1973{
1974 xmlChar *str = NULL, *msg = NULL;
1975 xmlSchemaTypeType facetType;
1976 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1977
1978 xmlSchemaFormatNodeForError(&msg, actxt, node);
1979 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1980 facetType = XML_SCHEMA_FACET_ENUMERATION;
1981 /*
1982 * If enumerations are validated, one must not expect the
1983 * facet to be given.
1984 */
1985 } else
1986 facetType = facet->type;
1987 msg = xmlStrcat(msg, BAD_CAST "[");
1988 msg = xmlStrcat(msg, BAD_CAST "facet '");
1989 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
1990 msg = xmlStrcat(msg, BAD_CAST "'] ");
1991 if (message == NULL) {
1992 /*
1993 * Use a default message.
1994 */
1995 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1996 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1997 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1998
1999 char len[25], actLen[25];
2000
2001 /* FIXME, TODO: What is the max expected string length of the
2002 * this value?
2003 */
2004 if (nodeType == XML_ATTRIBUTE_NODE)
2005 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2006 else
2007 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2008
2009 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2010 snprintf(actLen, 24, "%lu", length);
2011
2012 if (facetType == XML_SCHEMA_FACET_LENGTH)
2013 msg = xmlStrcat(msg,
2014 BAD_CAST "this differs from the allowed length of '%s'.\n");
2015 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2016 msg = xmlStrcat(msg,
2017 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2018 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2019 msg = xmlStrcat(msg,
2020 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2021
2022 if (nodeType == XML_ATTRIBUTE_NODE)
2023 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2024 value, (const xmlChar *) actLen, (const xmlChar *) len);
2025 else
2026 xmlSchemaErr(actxt, error, node, (const char *) msg,
2027 (const xmlChar *) actLen, (const xmlChar *) len);
2028
2029 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2030 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2031 "of the set {%s}.\n");
2032 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2033 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2034 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2035 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2036 "by the pattern '%s'.\n");
2037 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2038 facet->value);
2039 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2040 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2041 "minimum value allowed ('%s').\n");
2042 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2043 facet->value);
2044 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2045 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2046 "maximum value allowed ('%s').\n");
2047 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2048 facet->value);
2049 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2050 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2051 "'%s'.\n");
2052 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2053 facet->value);
2054 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2055 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2056 "'%s'.\n");
2057 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2058 facet->value);
2059 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2060 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2061 "digits than are allowed ('%s').\n");
2062 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2063 facet->value);
2064 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2065 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2066 "digits than are allowed ('%s').\n");
2067 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2068 facet->value);
2069 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2070 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2071 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2072 } else {
2073 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2074 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2075 }
2076 } else {
2077 msg = xmlStrcat(msg, (const xmlChar *) message);
2078 msg = xmlStrcat(msg, BAD_CAST ".\n");
2079 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2080 }
2081 FREE_AND_NULL(str)
2082 xmlFree(msg);
2083}
2084
2085#define VERROR(err, type, msg) \
2086 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2087
2088#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2089
2090#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2091
2092#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2093
2094
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002095/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002096 * xmlSchemaPMissingAttrErr:
2097 * @ctxt: the schema validation context
2098 * @ownerDes: the designation of the owner
2099 * @ownerName: the name of the owner
2100 * @ownerItem: the owner as a schema object
2101 * @ownerElem: the owner as an element node
2102 * @node: the parent element node of the missing attribute node
2103 * @type: the corresponding type of the attribute node
2104 *
2105 * Reports an illegal attribute.
2106 */
2107static void
2108xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002109 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002110 xmlSchemaTypePtr ownerItem,
2111 xmlNodePtr ownerElem,
2112 const char *name,
2113 const char *message)
2114{
2115 xmlChar *des = NULL;
2116
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002117 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2118
Daniel Veillardc0826a72004-08-10 14:17:33 +00002119 if (message != NULL)
2120 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002121 else
2122 xmlSchemaPErr(ctxt, ownerElem, error,
2123 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002124 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002125 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002126}
2127
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002128
Daniel Veillardc0826a72004-08-10 14:17:33 +00002129/**
2130 * xmlSchemaPResCompAttrErr:
2131 * @ctxt: the schema validation context
2132 * @error: the error code
2133 * @ownerDes: the designation of the owner
2134 * @ownerItem: the owner as a schema object
2135 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002136 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002137 * @refName: the referenced local name
2138 * @refURI: the referenced namespace URI
2139 * @message: optional message
2140 *
2141 * Used to report QName attribute values that failed to resolve
2142 * to schema components.
2143 */
2144static void
2145xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002146 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002147 xmlSchemaTypePtr ownerItem,
2148 xmlNodePtr ownerElem,
2149 const char *name,
2150 const xmlChar *refName,
2151 const xmlChar *refURI,
2152 xmlSchemaTypeType refType,
2153 const char *refTypeStr)
2154{
2155 xmlChar *des = NULL, *strA = NULL;
2156
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002157 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002158 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002159 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2160 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002161 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2163 "%s.\n", BAD_CAST des, BAD_CAST name,
2164 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002165 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002166 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002167 FREE_AND_NULL(strA)
2168}
2169
William M. Brack2f2a6632004-08-20 23:09:47 +00002170/**
2171 * xmlSchemaPCustomAttrErr:
2172 * @ctxt: the schema parser context
2173 * @error: the error code
2174 * @ownerDes: the designation of the owner
2175 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002176 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002177 *
2178 * Reports an illegal attribute during the parse.
2179 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002180static void
2181xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002182 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002183 xmlChar **ownerDes,
2184 xmlSchemaTypePtr ownerItem,
2185 xmlAttrPtr attr,
2186 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002187{
2188 xmlChar *des = NULL;
2189
2190 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002191 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002192 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002193 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002194 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002195 } else
2196 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002198 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002199 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2200 if (ownerDes == NULL)
2201 FREE_AND_NULL(des);
2202}
2203
2204/**
2205 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002206 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002207 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002208 * @ownerDes: the designation of the attribute's owner
2209 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002210 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002211 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002212 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002213 */
2214static void
2215xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002216 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002217 xmlChar **ownerDes,
2218 xmlSchemaTypePtr ownerItem,
2219 xmlAttrPtr attr)
2220{
2221 xmlChar *des = NULL, *strA = NULL;
2222
2223 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002224 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002225 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002226 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002227 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002228 } else
2229 des = *ownerDes;
2230 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2231 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2232 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002233 if (ownerDes == NULL)
2234 FREE_AND_NULL(des);
2235 FREE_AND_NULL(strA);
2236}
2237
William M. Brack2f2a6632004-08-20 23:09:47 +00002238/**
2239 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002240 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002241 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002242 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002243 * @itemElem: the node of the schema item
2244 *
2245 * Creates a designation for an item.
2246 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002247static void
2248xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002249 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002250 xmlSchemaTypePtr item,
2251 xmlNodePtr itemElem)
2252{
2253 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002254 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002255 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002256 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002257 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002258 } else
2259 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002260}
2261
William M. Brack2f2a6632004-08-20 23:09:47 +00002262/**
2263 * xmlSchemaPCustomErr:
2264 * @ctxt: the schema parser context
2265 * @error: the error code
2266 * @itemDes: the designation of the schema item
2267 * @item: the schema item
2268 * @itemElem: the node of the schema item
2269 * @message: the error message
2270 * @str1: an optional param for the error message
2271 * @str2: an optional param for the error message
2272 * @str3: an optional param for the error message
2273 *
2274 * Reports an error during parsing.
2275 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002276static void
2277xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002278 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002279 xmlChar **itemDes,
2280 xmlSchemaTypePtr item,
2281 xmlNodePtr itemElem,
2282 const char *message,
2283 const xmlChar *str1,
2284 const xmlChar *str2,
2285 const xmlChar *str3)
2286{
2287 xmlChar *des = NULL, *msg = NULL;
2288
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002289 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002290 msg = xmlStrdup(BAD_CAST "%s: ");
2291 msg = xmlStrcat(msg, (const xmlChar *) message);
2292 msg = xmlStrcat(msg, BAD_CAST ".\n");
2293 if ((itemElem == NULL) && (item != NULL))
2294 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002295 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002296 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2297 if (itemDes == NULL)
2298 FREE_AND_NULL(des);
2299 FREE_AND_NULL(msg);
2300}
2301
William M. Brack2f2a6632004-08-20 23:09:47 +00002302/**
2303 * xmlSchemaPCustomErr:
2304 * @ctxt: the schema parser context
2305 * @error: the error code
2306 * @itemDes: the designation of the schema item
2307 * @item: the schema item
2308 * @itemElem: the node of the schema item
2309 * @message: the error message
2310 * @str1: the optional param for the error message
2311 *
2312 * Reports an error during parsing.
2313 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002314static void
2315xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002316 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002317 xmlChar **itemDes,
2318 xmlSchemaTypePtr item,
2319 xmlNodePtr itemElem,
2320 const char *message,
2321 const xmlChar *str1)
2322{
2323 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2324 str1, NULL, NULL);
2325}
2326
William M. Brack2f2a6632004-08-20 23:09:47 +00002327/**
2328 * xmlSchemaPAttrUseErr:
2329 * @ctxt: the schema parser context
2330 * @error: the error code
2331 * @itemDes: the designation of the schema type
2332 * @item: the schema type
2333 * @itemElem: the node of the schema type
2334 * @attr: the invalid schema attribute
2335 * @message: the error message
2336 * @str1: the optional param for the error message
2337 *
2338 * Reports an attribute use error during parsing.
2339 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002340static void
2341xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002342 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002343 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002344 const xmlSchemaAttributePtr attr,
2345 const char *message,
2346 const xmlChar *str1)
2347{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002348 xmlChar *str = NULL, *msg = NULL;
2349 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2350 msg = xmlStrcat(msg, BAD_CAST ", ");
2351 msg = xmlStrcat(msg,
2352 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2353 (xmlSchemaTypePtr) attr, NULL));
2354 FREE_AND_NULL(str);
2355 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002356 msg = xmlStrcat(msg, (const xmlChar *) message);
2357 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002358 xmlSchemaPErr(ctxt, attr->node, error,
2359 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002360 xmlFree(msg);
2361}
2362
William M. Brack2f2a6632004-08-20 23:09:47 +00002363/**
2364 * xmlSchemaPIllegalFacetAtomicErr:
2365 * @ctxt: the schema parser context
2366 * @error: the error code
2367 * @itemDes: the designation of the type
2368 * @item: the schema type
2369 * @baseItem: the base type of type
2370 * @facet: the illegal facet
2371 *
2372 * Reports an illegal facet for atomic simple types.
2373 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002374static void
2375xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002376 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002377 xmlChar **itemDes,
2378 xmlSchemaTypePtr item,
2379 xmlSchemaTypePtr baseItem,
2380 xmlSchemaFacetPtr facet)
2381{
2382 xmlChar *des = NULL, *strT = NULL;
2383
2384 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2385 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2386 "%s: The facet '%s' is not allowed on types derived from the "
2387 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002388 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002389 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002390 NULL, NULL);
2391 if (itemDes == NULL)
2392 FREE_AND_NULL(des);
2393 FREE_AND_NULL(strT);
2394}
2395
William M. Brack2f2a6632004-08-20 23:09:47 +00002396/**
2397 * xmlSchemaPIllegalFacetListUnionErr:
2398 * @ctxt: the schema parser context
2399 * @error: the error code
2400 * @itemDes: the designation of the schema item involved
2401 * @item: the schema item involved
2402 * @facet: the illegal facet
2403 *
2404 * Reports an illegal facet for <list> and <union>.
2405 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002406static void
2407xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002408 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002409 xmlChar **itemDes,
2410 xmlSchemaTypePtr item,
2411 xmlSchemaFacetPtr facet)
2412{
2413 xmlChar *des = NULL, *strT = NULL;
2414
2415 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002416 xmlSchemaPErr(ctxt, item->node, error,
2417 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002418 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002419 if (itemDes == NULL)
2420 FREE_AND_NULL(des);
2421 FREE_AND_NULL(strT);
2422}
2423
2424/**
2425 * xmlSchemaPMutualExclAttrErr:
2426 * @ctxt: the schema validation context
2427 * @error: the error code
2428 * @elemDes: the designation of the parent element node
2429 * @attr: the bad attribute node
2430 * @type: the corresponding type of the attribute node
2431 *
2432 * Reports an illegal attribute.
2433 */
2434static void
2435xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2436 xmlParserErrors error,
2437 xmlChar **ownerDes,
2438 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002439 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002440 const char *name1,
2441 const char *name2)
2442{
2443 xmlChar *des = NULL;
2444
2445 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002446 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002447 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002448 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002449 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002450 } else
2451 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002452 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002453 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002454 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2455 if (ownerDes == NULL)
2456 FREE_AND_NULL(des)
2457}
2458
2459/**
2460 * xmlSchemaPSimpleTypeErr:
2461 * @ctxt: the schema validation context
2462 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002463 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002464 * @ownerDes: the designation of the owner
2465 * @ownerItem: the schema object if existent
2466 * @node: the validated node
2467 * @value: the validated value
2468 *
2469 * Reports a simple type validation error.
2470 * TODO: Should this report the value of an element as well?
2471 */
2472static void
2473xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2474 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002475 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002476 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002477 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002478 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002479 const xmlChar *value,
2480 const char *message,
2481 const xmlChar *str1,
2482 const xmlChar *str2)
2483{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002484 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002485
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002486 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487 if (message == NULL) {
2488 /*
2489 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002490 */
2491 if (type != NULL) {
2492 if (node->type == XML_ATTRIBUTE_NODE)
2493 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2494 else
2495 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2496 "valid value of ");
2497 if (! xmlSchemaIsGlobalItem(type))
2498 msg = xmlStrcat(msg, BAD_CAST "the local ");
2499 else
2500 msg = xmlStrcat(msg, BAD_CAST "the ");
2501
2502 if (VARIETY_ATOMIC(type))
2503 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2504 else if (VARIETY_LIST(type))
2505 msg = xmlStrcat(msg, BAD_CAST "list type");
2506 else if (VARIETY_UNION(type))
2507 msg = xmlStrcat(msg, BAD_CAST "union type");
2508
2509 if (xmlSchemaIsGlobalItem(type)) {
2510 xmlChar *str = NULL;
2511 msg = xmlStrcat(msg, BAD_CAST " '");
2512 if (type->builtInType != 0) {
2513 msg = xmlStrcat(msg, BAD_CAST "xs:");
2514 msg = xmlStrcat(msg, type->name);
2515 } else
2516 msg = xmlStrcat(msg,
2517 xmlSchemaFormatQName(&str,
2518 type->targetNamespace, type->name));
2519 msg = xmlStrcat(msg, BAD_CAST "'.");
2520 FREE_AND_NULL(str);
2521 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002522 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002523 if (node->type == XML_ATTRIBUTE_NODE)
2524 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2525 else
2526 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2527 "valid.");
2528 }
2529 if (expected) {
2530 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2531 msg = xmlStrcat(msg, BAD_CAST expected);
2532 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2533 } else
2534 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002535 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002536 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2537 else
2538 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2539 } else {
2540 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2541 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002542 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002543 /* Cleanup. */
2544 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002545}
2546
William M. Brack2f2a6632004-08-20 23:09:47 +00002547/**
2548 * xmlSchemaPContentErr:
2549 * @ctxt: the schema parser context
2550 * @error: the error code
2551 * @onwerDes: the designation of the holder of the content
2552 * @ownerItem: the owner item of the holder of the content
2553 * @ownerElem: the node of the holder of the content
2554 * @child: the invalid child node
2555 * @message: the optional error message
2556 * @content: the optional string describing the correct content
2557 *
2558 * Reports an error concerning the content of a schema element.
2559 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002560static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002561xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002562 xmlParserErrors error,
2563 xmlChar **ownerDes,
2564 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002565 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002566 xmlNodePtr child,
2567 const char *message,
2568 const char *content)
2569{
2570 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002571
Daniel Veillardc0826a72004-08-10 14:17:33 +00002572 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002573 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002574 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002575 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002576 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002577 } else
2578 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002579 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002580 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2581 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002582 BAD_CAST des, BAD_CAST message);
2583 else {
2584 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002585 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2586 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002587 BAD_CAST des, BAD_CAST content);
2588 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002589 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2590 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002591 BAD_CAST des, NULL);
2592 }
2593 }
2594 if (ownerDes == NULL)
2595 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002596}
2597
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002598/************************************************************************
2599 * *
2600 * Streamable error functions *
2601 * *
2602 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002603
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002604
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002605
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002606
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002607/************************************************************************
2608 * *
2609 * Validation helper functions *
2610 * *
2611 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002612
Daniel Veillardc0826a72004-08-10 14:17:33 +00002613
Daniel Veillard4255d502002-04-16 15:50:10 +00002614/************************************************************************
2615 * *
2616 * Allocation functions *
2617 * *
2618 ************************************************************************/
2619
2620/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002621 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002622 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002623 *
2624 * Allocate a new Schema structure.
2625 *
2626 * Returns the newly allocated structure or NULL in case or error
2627 */
2628static xmlSchemaPtr
2629xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2630{
2631 xmlSchemaPtr ret;
2632
2633 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2634 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002635 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002636 return (NULL);
2637 }
2638 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002639 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002640 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002641
2642 return (ret);
2643}
2644
2645/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002646 * xmlSchemaNewSchema:
2647 * @ctxt: a schema validation context
2648 *
2649 * Allocate a new Schema structure.
2650 *
2651 * Returns the newly allocated structure or NULL in case or error
2652 */
2653static xmlSchemaAssemblePtr
2654xmlSchemaNewAssemble(void)
2655{
2656 xmlSchemaAssemblePtr ret;
2657
2658 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2659 if (ret == NULL) {
2660 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2661 return (NULL);
2662 }
2663 memset(ret, 0, sizeof(xmlSchemaAssemble));
2664 ret->items = NULL;
2665 return (ret);
2666}
2667
2668/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002669 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002670 *
2671 * Allocate a new Facet structure.
2672 *
2673 * Returns the newly allocated structure or NULL in case or error
2674 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002675xmlSchemaFacetPtr
2676xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002677{
2678 xmlSchemaFacetPtr ret;
2679
2680 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2681 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002682 return (NULL);
2683 }
2684 memset(ret, 0, sizeof(xmlSchemaFacet));
2685
2686 return (ret);
2687}
2688
2689/**
2690 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002691 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002692 * @node: a node
2693 *
2694 * Allocate a new annotation structure.
2695 *
2696 * Returns the newly allocated structure or NULL in case or error
2697 */
2698static xmlSchemaAnnotPtr
2699xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2700{
2701 xmlSchemaAnnotPtr ret;
2702
2703 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2704 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002705 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002706 return (NULL);
2707 }
2708 memset(ret, 0, sizeof(xmlSchemaAnnot));
2709 ret->content = node;
2710 return (ret);
2711}
2712
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002713static xmlSchemaItemListPtr
2714xmlSchemaNewItemList(void)
2715{
2716 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002717
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002718 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2719 if (ret == NULL) {
2720 xmlSchemaPErrMemory(NULL,
2721 "allocating an item list structure", NULL);
2722 return (NULL);
2723 }
2724 memset(ret, 0, sizeof(xmlSchemaItemList));
2725 return (ret);
2726}
2727
2728/**
2729 * xmlSchemaAddElementSubstitutionMember:
2730 * @pctxt: a schema parser context
2731 * @head: the head of the substitution group
2732 * @member: the new member of the substitution group
2733 *
2734 * Allocate a new annotation structure.
2735 *
2736 * Returns the newly allocated structure or NULL in case or error
2737 */
2738static int
2739xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2740 xmlSchemaElementPtr head,
2741 xmlSchemaElementPtr member)
2742{
2743 xmlSchemaSubstGroupPtr substGroup;
2744
2745 if (pctxt == NULL)
2746 return (-1);
2747
2748 if (pctxt->substGroups == NULL) {
2749 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2750 if (pctxt->substGroups == NULL)
2751 return (-1);
2752 }
2753 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2754 head->targetNamespace);
2755 if (substGroup == NULL) {
2756 int res;
2757
2758 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2759 if (substGroup == NULL) {
2760 xmlSchemaPErrMemory(NULL,
2761 "xmlSchemaAddElementSubstitution, allocating a substitution "
2762 "group container",
2763 NULL);
2764 return (-1);
2765 }
2766 substGroup->members = xmlSchemaNewItemList();
2767 if (substGroup->members == NULL) {
2768 xmlFree(substGroup);
2769 return (-1);
2770 }
2771 substGroup->head = head;
2772
2773 res = xmlHashAddEntry2(pctxt->substGroups,
2774 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002775 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002776 xmlFree(substGroup->members);
2777 xmlFree(substGroup);
2778 xmlSchemaPErr(pctxt, member->node,
2779 XML_SCHEMAP_INTERNAL,
2780 "Internal error: xmlSchemaAddElementSubstitution, "
2781 "failed to add a new substitution group container for "
2782 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002783 return (-1);
2784 }
2785 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002786 if (substGroup->members->items == NULL) {
2787 substGroup->members->items = (void **) xmlMalloc(
2788 5 * sizeof(xmlSchemaElementPtr));
2789 if (substGroup->members->items == NULL) {
2790 xmlSchemaPErrMemory(NULL,
2791 "allocating list of substitution group members", NULL);
2792 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002793 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002794 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002795 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002796 substGroup->members->nbItems) {
2797 substGroup->members->sizeItems *= 2;
2798 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002799 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002800 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2801 if (substGroup->members->items == NULL) {
2802 xmlSchemaPErrMemory(NULL,
2803 "re-allocating list of substitution group members", NULL);
2804 substGroup->members->sizeItems = 0;
2805 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002806 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002807 }
2808 ((xmlSchemaElementPtr *) substGroup->members->items)
2809 [substGroup->members->nbItems++] = (void *) member;
2810 return (0);
2811}
2812
2813/**
2814 * xmlSchemaGetElementSubstitutionGroup:
2815 * @pctxt: a schema parser context
2816 * @head: the head of the substitution group
2817 * @member: the new member of the substitution group
2818 *
2819 * Allocate a new annotation structure.
2820 *
2821 * Returns the newly allocated structure or NULL in case or error
2822 */
2823static xmlSchemaSubstGroupPtr
2824xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2825 xmlSchemaElementPtr head)
2826{
2827 if (pctxt == NULL)
2828 return (NULL);
2829
2830 if (pctxt->substGroups == NULL)
2831 return (NULL);
2832
2833 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2834 head->name, head->targetNamespace));
2835}
2836
2837/**
2838 * xmlSchemaFreeItemList:
2839 * @annot: a schema type structure
2840 *
2841 * Deallocate a annotation structure
2842 */
2843static void
2844xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2845{
2846 if (list == NULL)
2847 return;
2848 if (list->items != NULL)
2849 xmlFree(list->items);
2850 xmlFree(list);
2851}
2852
Daniel Veillard4255d502002-04-16 15:50:10 +00002853/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002854 * xmlSchemaFreeAnnot:
2855 * @annot: a schema type structure
2856 *
2857 * Deallocate a annotation structure
2858 */
2859static void
2860xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2861{
2862 if (annot == NULL)
2863 return;
2864 xmlFree(annot);
2865}
2866
2867/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002868 * xmlSchemaFreeImport:
2869 * @import: a schema import structure
2870 *
2871 * Deallocate an import structure
2872 */
2873static void
2874xmlSchemaFreeImport(xmlSchemaImportPtr import)
2875{
2876 if (import == NULL)
2877 return;
2878
2879 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002880 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002881 xmlFree(import);
2882}
2883
2884/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002885 * xmlSchemaFreeInclude:
2886 * @include: a schema include structure
2887 *
2888 * Deallocate an include structure
2889 */
2890static void
2891xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2892{
2893 if (include == NULL)
2894 return;
2895
2896 xmlFreeDoc(include->doc);
2897 xmlFree(include);
2898}
2899
2900/**
2901 * xmlSchemaFreeIncludeList:
2902 * @includes: a schema include list
2903 *
2904 * Deallocate an include structure
2905 */
2906static void
2907xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2908{
2909 xmlSchemaIncludePtr next;
2910
2911 while (includes != NULL) {
2912 next = includes->next;
2913 xmlSchemaFreeInclude(includes);
2914 includes = next;
2915 }
2916}
2917
2918/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002919 * xmlSchemaFreeNotation:
2920 * @schema: a schema notation structure
2921 *
2922 * Deallocate a Schema Notation structure.
2923 */
2924static void
2925xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2926{
2927 if (nota == NULL)
2928 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002929 xmlFree(nota);
2930}
2931
2932/**
2933 * xmlSchemaFreeAttribute:
2934 * @schema: a schema attribute structure
2935 *
2936 * Deallocate a Schema Attribute structure.
2937 */
2938static void
2939xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2940{
2941 if (attr == NULL)
2942 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002943 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002944 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002945 if (attr->defVal != NULL)
2946 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002947 xmlFree(attr);
2948}
2949
2950/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002951 * xmlSchemaFreeWildcardNsSet:
2952 * set: a schema wildcard namespace
2953 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002954 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002955 */
2956static void
2957xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2958{
2959 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002960
Daniel Veillard3646d642004-06-02 19:19:14 +00002961 while (set != NULL) {
2962 next = set->next;
2963 xmlFree(set);
2964 set = next;
2965 }
2966}
2967
2968/**
2969 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002970 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002971 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002972 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002973 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002974void
Daniel Veillard3646d642004-06-02 19:19:14 +00002975xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2976{
2977 if (wildcard == NULL)
2978 return;
2979 if (wildcard->annot != NULL)
2980 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002981 if (wildcard->nsSet != NULL)
2982 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2983 if (wildcard->negNsSet != NULL)
2984 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002985 xmlFree(wildcard);
2986}
2987
2988/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002989 * xmlSchemaFreeAttributeGroup:
2990 * @schema: a schema attribute group structure
2991 *
2992 * Deallocate a Schema Attribute Group structure.
2993 */
2994static void
2995xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2996{
2997 if (attr == NULL)
2998 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002999 if (attr->annot != NULL)
3000 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003001 xmlFree(attr);
3002}
3003
3004/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003005 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003006 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003007 *
3008 * Deallocate a list of schema attribute uses.
3009 */
3010static void
3011xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3012{
3013 xmlSchemaAttributeLinkPtr next;
3014
3015 while (attrUse != NULL) {
3016 next = attrUse->next;
3017 xmlFree(attrUse);
3018 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003019 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003020}
3021
3022/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003023 * xmlSchemaFreeQNameRef:
3024 * @item: a QName reference structure
3025 *
3026 * Deallocatea a QName reference structure.
3027 */
3028static void
3029xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3030{
3031 xmlFree(item);
3032}
3033
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003034/**
3035 * xmlSchemaFreeQNameRef:
3036 * @item: a QName reference structure
3037 *
3038 * Deallocatea a QName reference structure.
3039 */
3040static void
3041xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3042{
3043 if (item == NULL)
3044 return;
3045 if (item->members != NULL)
3046 xmlSchemaFreeItemList(item->members);
3047 xmlFree(item);
3048}
3049
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003050static int
3051xmlSchemaAddVolatile(xmlSchemaPtr schema,
3052 xmlSchemaBasicItemPtr item)
3053{
3054 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003055
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003056 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003057 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003058 if (schema->volatiles == NULL) {
3059 xmlSchemaPErrMemory(NULL,
3060 "allocating list of volatiles", NULL);
3061 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003062 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003063 }
3064 list = (xmlSchemaItemListPtr) schema->volatiles;
3065 if (list->items == NULL) {
3066 list->items = (void **) xmlMalloc(
3067 20 * sizeof(xmlSchemaBasicItemPtr));
3068 if (list->items == NULL) {
3069 xmlSchemaPErrMemory(NULL,
3070 "allocating new volatile item buffer", NULL);
3071 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003072 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003073 list->sizeItems = 20;
3074 } else if (list->sizeItems <= list->nbItems) {
3075 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003076 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003077 list->sizeItems * sizeof(xmlSchemaTypePtr));
3078 if (list->items == NULL) {
3079 xmlSchemaPErrMemory(NULL,
3080 "growing volatile item buffer", NULL);
3081 list->sizeItems = 0;
3082 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003083 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003084 }
3085 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3086 return (0);
3087}
3088
3089/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003090 * xmlSchemaFreeTypeLinkList:
3091 * @alink: a type link
3092 *
3093 * Deallocate a list of types.
3094 */
3095static void
3096xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3097{
3098 xmlSchemaTypeLinkPtr next;
3099
3100 while (link != NULL) {
3101 next = link->next;
3102 xmlFree(link);
3103 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003104 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003105}
3106
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003107static void
3108xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3109{
3110 xmlSchemaIDCStateObjPtr next;
3111 while (sto != NULL) {
3112 next = sto->next;
3113 if (sto->history != NULL)
3114 xmlFree(sto->history);
3115 if (sto->xpathCtxt != NULL)
3116 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3117 xmlFree(sto);
3118 sto = next;
3119 }
3120}
3121
3122/**
3123 * xmlSchemaFreeIDC:
3124 * @idc: a identity-constraint definition
3125 *
3126 * Deallocates an identity-constraint definition.
3127 */
3128static void
3129xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3130{
3131 xmlSchemaIDCSelectPtr cur, prev;
3132
3133 if (idcDef == NULL)
3134 return;
3135 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003136 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003137 /* Selector */
3138 if (idcDef->selector != NULL) {
3139 if (idcDef->selector->xpathComp != NULL)
3140 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3141 xmlFree(idcDef->selector);
3142 }
3143 /* Fields */
3144 if (idcDef->fields != NULL) {
3145 cur = idcDef->fields;
3146 do {
3147 prev = cur;
3148 cur = cur->next;
3149 if (prev->xpathComp != NULL)
3150 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003151 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003152 } while (cur != NULL);
3153 }
3154 xmlFree(idcDef);
3155}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003156
Daniel Veillard01fa6152004-06-29 17:04:39 +00003157/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 * xmlSchemaFreeElement:
3159 * @schema: a schema element structure
3160 *
3161 * Deallocate a Schema Element structure.
3162 */
3163static void
3164xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3165{
3166 if (elem == NULL)
3167 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003168 if (elem->annot != NULL)
3169 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003170 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003171 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003172 if (elem->defVal != NULL)
3173 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003174 xmlFree(elem);
3175}
3176
3177/**
3178 * xmlSchemaFreeFacet:
3179 * @facet: a schema facet structure
3180 *
3181 * Deallocate a Schema Facet structure.
3182 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003183void
Daniel Veillard4255d502002-04-16 15:50:10 +00003184xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3185{
3186 if (facet == NULL)
3187 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003188 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003189 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003190 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003191 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003192 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003193 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003194 xmlFree(facet);
3195}
3196
3197/**
3198 * xmlSchemaFreeType:
3199 * @type: a schema type structure
3200 *
3201 * Deallocate a Schema Type structure.
3202 */
3203void
3204xmlSchemaFreeType(xmlSchemaTypePtr type)
3205{
3206 if (type == NULL)
3207 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003208 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003209 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003212
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003213 facet = type->facets;
3214 while (facet != NULL) {
3215 next = facet->next;
3216 xmlSchemaFreeFacet(facet);
3217 facet = next;
3218 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003219 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003220 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3221 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003222 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003223 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003224 if (type->memberTypes != NULL)
3225 xmlSchemaFreeTypeLinkList(type->memberTypes);
3226 if (type->facetSet != NULL) {
3227 xmlSchemaFacetLinkPtr next, link;
3228
3229 link = type->facetSet;
3230 do {
3231 next = link->next;
3232 xmlFree(link);
3233 link = next;
3234 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003235 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003236 if (type->contModel != NULL)
3237 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003238 xmlFree(type);
3239}
3240
3241/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003242 * xmlSchemaFreeModelGroupDef:
3243 * @item: a schema model group definition
3244 *
3245 * Deallocates a schema model group definition.
3246 */
3247static void
3248xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3249{
3250 if (item->annot != NULL)
3251 xmlSchemaFreeAnnot(item->annot);
3252 xmlFree(item);
3253}
3254
3255/**
3256 * xmlSchemaFreeModelGroup:
3257 * @item: a schema model group
3258 *
3259 * Deallocates a schema model group structure.
3260 */
3261static void
3262xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3263{
3264 if (item->annot != NULL)
3265 xmlSchemaFreeAnnot(item->annot);
3266 xmlFree(item);
3267}
3268
3269/**
3270 * xmlSchemaFreeParticle:
3271 * @type: a schema type structure
3272 *
3273 * Deallocate a Schema Type structure.
3274 */
3275static void
3276xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3277{
3278 if (item->annot != NULL)
3279 xmlSchemaFreeAnnot(item->annot);
3280 xmlFree(item);
3281}
3282
3283/**
3284 * xmlSchemaFreeMiscComponents:
3285 * @item: a schema component
3286 *
3287 * Deallocates misc. schema component structures.
3288 */
3289static void
3290xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3291{
3292 if (item == NULL)
3293 return;
3294 switch (item->type) {
3295 case XML_SCHEMA_TYPE_PARTICLE:
3296 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3297 return;
3298 case XML_SCHEMA_TYPE_SEQUENCE:
3299 case XML_SCHEMA_TYPE_CHOICE:
3300 case XML_SCHEMA_TYPE_ALL:
3301 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3302 return;
3303 case XML_SCHEMA_TYPE_ANY:
3304 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3305 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3306 break;
3307 default:
3308 /* TODO: This should never be hit. */
3309 TODO
3310 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003311 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003312}
3313
3314static void
3315xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3316{
3317 if (schema->volatiles == NULL)
3318 return;
3319 {
3320 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3321 xmlSchemaTreeItemPtr item;
3322 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003323
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003324 for (i = 0; i < list->nbItems; i++) {
3325 if (list->items[i] != NULL) {
3326 item = (xmlSchemaTreeItemPtr) list->items[i];
3327 switch (item->type) {
3328 case XML_SCHEMA_EXTRA_QNAMEREF:
3329 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3330 break;
3331 default:
3332 xmlSchemaFreeMiscComponents(item);
3333 }
3334 }
3335 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003336 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003337 }
3338}
3339/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003340 * xmlSchemaFreeTypeList:
3341 * @type: a schema type structure
3342 *
3343 * Deallocate a Schema Type structure.
3344 */
3345static void
3346xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3347{
3348 xmlSchemaTypePtr next;
3349
3350 while (type != NULL) {
3351 next = type->redef;
3352 xmlSchemaFreeType(type);
3353 type = next;
3354 }
3355}
3356
3357/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003358 * xmlSchemaFree:
3359 * @schema: a schema structure
3360 *
3361 * Deallocate a Schema structure.
3362 */
3363void
3364xmlSchemaFree(xmlSchemaPtr schema)
3365{
3366 if (schema == NULL)
3367 return;
3368
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003369 if (schema->volatiles != NULL)
3370 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003371 if (schema->notaDecl != NULL)
3372 xmlHashFree(schema->notaDecl,
3373 (xmlHashDeallocator) xmlSchemaFreeNotation);
3374 if (schema->attrDecl != NULL)
3375 xmlHashFree(schema->attrDecl,
3376 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3377 if (schema->attrgrpDecl != NULL)
3378 xmlHashFree(schema->attrgrpDecl,
3379 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3380 if (schema->elemDecl != NULL)
3381 xmlHashFree(schema->elemDecl,
3382 (xmlHashDeallocator) xmlSchemaFreeElement);
3383 if (schema->typeDecl != NULL)
3384 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003385 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003386 if (schema->groupDecl != NULL)
3387 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003388 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003389 if (schema->idcDef != NULL)
3390 xmlHashFree(schema->idcDef,
3391 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003392 if (schema->schemasImports != NULL)
3393 xmlHashFree(schema->schemasImports,
3394 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003395 if (schema->includes != NULL) {
3396 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3397 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003398 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003399 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003400 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003401 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003402 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003403 xmlFree(schema);
3404}
3405
3406/************************************************************************
3407 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003408 * Debug functions *
3409 * *
3410 ************************************************************************/
3411
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003412#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003413
Daniel Veillard4255d502002-04-16 15:50:10 +00003414/**
3415 * xmlSchemaElementDump:
3416 * @elem: an element
3417 * @output: the file output
3418 *
3419 * Dump the element
3420 */
3421static void
3422xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003424 const xmlChar * namespace ATTRIBUTE_UNUSED,
3425 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003426{
3427 if (elem == NULL)
3428 return;
3429
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003430 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3431 fprintf(output, "Particle: %s", name);
3432 fprintf(output, ", term element: %s", elem->ref);
3433 if (elem->refNs != NULL)
3434 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003435 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003436 fprintf(output, "Element");
3437 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3438 fprintf(output, " (global)");
3439 fprintf(output, ": %s ", elem->name);
3440 if (namespace != NULL)
3441 fprintf(output, "ns %s", namespace);
3442 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003443 fprintf(output, "\n");
3444 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003445 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003446 if (elem->maxOccurs >= UNBOUNDED)
3447 fprintf(output, "max: unbounded\n");
3448 else if (elem->maxOccurs != 1)
3449 fprintf(output, "max: %d\n", elem->maxOccurs);
3450 else
3451 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003452 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003453 /*
3454 * Misc other properties.
3455 */
3456 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3457 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3458 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3459 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3460 (elem->id != NULL)) {
3461 fprintf(output, " props: ");
3462 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3463 fprintf(output, "[fixed] ");
3464 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3465 fprintf(output, "[default] ");
3466 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3467 fprintf(output, "[abstract] ");
3468 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3469 fprintf(output, "[nillable] ");
3470 if (elem->id != NULL)
3471 fprintf(output, "[id: '%s'] ", elem->id);
3472 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003473 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003474 /*
3475 * Default/fixed value.
3476 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003477 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003478 fprintf(output, " value: '%s'\n", elem->value);
3479 /*
3480 * Type.
3481 */
3482 if (elem->namedType != NULL) {
3483 fprintf(output, " type: %s ", elem->namedType);
3484 if (elem->namedTypeNs != NULL)
3485 fprintf(output, "ns %s\n", elem->namedTypeNs);
3486 else
3487 fprintf(output, "\n");
3488 }
3489 /*
3490 * Substitution group.
3491 */
3492 if (elem->substGroup != NULL) {
3493 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3494 if (elem->substGroupNs != NULL)
3495 fprintf(output, "ns %s\n", elem->substGroupNs);
3496 else
3497 fprintf(output, "\n");
3498 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003499}
3500
3501/**
3502 * xmlSchemaAnnotDump:
3503 * @output: the file output
3504 * @annot: a annotation
3505 *
3506 * Dump the annotation
3507 */
3508static void
3509xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3510{
3511 xmlChar *content;
3512
3513 if (annot == NULL)
3514 return;
3515
3516 content = xmlNodeGetContent(annot->content);
3517 if (content != NULL) {
3518 fprintf(output, " Annot: %s\n", content);
3519 xmlFree(content);
3520 } else
3521 fprintf(output, " Annot: empty\n");
3522}
3523
3524/**
3525 * xmlSchemaTypeDump:
3526 * @output: the file output
3527 * @type: a type structure
3528 *
3529 * Dump a SchemaType structure
3530 */
3531static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003532xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3533{
3534 xmlChar *str = NULL;
3535 xmlSchemaTreeItemPtr term;
3536 char shift[100];
3537 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003538
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003539 if (particle == NULL)
3540 return;
3541 for (i = 0;((i < depth) && (i < 25));i++)
3542 shift[2 * i] = shift[2 * i + 1] = ' ';
3543 shift[2 * i] = shift[2 * i + 1] = 0;
3544 fprintf(output, shift);
3545 if (particle->children == NULL) {
3546 fprintf(output, "MISSING particle term\n");
3547 return;
3548 }
3549 term = particle->children;
3550 switch (term->type) {
3551 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003552 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003553 ((xmlSchemaElementPtr)term)->targetNamespace,
3554 ((xmlSchemaElementPtr)term)->name));
3555 break;
3556 case XML_SCHEMA_TYPE_SEQUENCE:
3557 fprintf(output, "SEQUENCE");
3558 break;
3559 case XML_SCHEMA_TYPE_CHOICE:
3560 fprintf(output, "CHOICE");
3561 break;
3562 case XML_SCHEMA_TYPE_ALL:
3563 fprintf(output, "ALL");
3564 break;
3565 case XML_SCHEMA_TYPE_ANY:
3566 fprintf(output, "ANY");
3567 break;
3568 default:
3569 fprintf(output, "UNKNOWN\n");
3570 return;
3571 }
3572 if (particle->minOccurs != 1)
3573 fprintf(output, " min: %d", particle->minOccurs);
3574 if (particle->maxOccurs >= UNBOUNDED)
3575 fprintf(output, " max: unbounded");
3576 else if (particle->maxOccurs != 1)
3577 fprintf(output, " max: %d", particle->maxOccurs);
3578 fprintf(output, "\n");
3579 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3580 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3581 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3582 (term->children != NULL)) {
3583 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3584 output, depth +1);
3585 }
3586 if (particle->next != NULL)
3587 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3588 output, depth);
3589}
3590/**
3591 * xmlSchemaTypeDump:
3592 * @output: the file output
3593 * @type: a type structure
3594 *
3595 * Dump a SchemaType structure
3596 */
3597static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003598xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3599{
3600 if (type == NULL) {
3601 fprintf(output, "Type: NULL\n");
3602 return;
3603 }
3604 fprintf(output, "Type: ");
3605 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003606 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003607 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003608 fprintf(output, "no name ");
3609 if (type->targetNamespace != NULL)
3610 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 switch (type->type) {
3612 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003613 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 break;
3615 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003616 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003617 break;
3618 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003619 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003620 break;
3621 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003622 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 break;
3624 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003625 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003626 break;
3627 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003628 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 break;
3630 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003631 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 break;
3633 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003634 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003635 break;
3636 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003637 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 break;
3639 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003640 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003641 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003642 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003643 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003644 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003645 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003646 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003647 break;
3648 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003649 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 break;
3651 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003652 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003653 break;
3654 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003655 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003656 break;
3657 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003658 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003659 break;
3660 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003661 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003662 break;
3663 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003664 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003665 break;
3666 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003667 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003668 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003669 }
3670 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003671 if (type->base != NULL) {
3672 fprintf(output, " base type: %s", type->base);
3673 if (type->baseNs != NULL)
3674 fprintf(output, " ns %s\n", type->baseNs);
3675 else
3676 fprintf(output, "\n");
3677 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003678 if (type->annot != NULL)
3679 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003680#ifdef DUMP_CONTENT_MODEL
3681 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3682 (type->subtypes != NULL)) {
3683 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3684 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003686#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003687}
3688
3689/**
3690 * xmlSchemaDump:
3691 * @output: the file output
3692 * @schema: a schema structure
3693 *
3694 * Dump a Schema structure.
3695 */
3696void
3697xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3698{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003699 if (output == NULL)
3700 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003701 if (schema == NULL) {
3702 fprintf(output, "Schemas: NULL\n");
3703 return;
3704 }
3705 fprintf(output, "Schemas: ");
3706 if (schema->name != NULL)
3707 fprintf(output, "%s, ", schema->name);
3708 else
3709 fprintf(output, "no name, ");
3710 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003711 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003712 else
3713 fprintf(output, "no target namespace");
3714 fprintf(output, "\n");
3715 if (schema->annot != NULL)
3716 xmlSchemaAnnotDump(output, schema->annot);
3717
3718 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3719 output);
3720 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003722}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003723
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003724#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003725/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003726 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003727 * @vctxt: the WXS validation context
3728 *
3729 * Displays the current IDC table for debug purposes.
3730 */
3731static void
3732xmlSchemaDebugDumpIDCTable(FILE * output,
3733 const xmlChar *namespaceName,
3734 const xmlChar *localName,
3735 xmlSchemaPSVIIDCBindingPtr bind)
3736{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003737 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003738 xmlSchemaPSVIIDCNodePtr tab;
3739 xmlSchemaPSVIIDCKeyPtr key;
3740 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003741
3742 fprintf(output, "IDC: TABLES on %s\n",
3743 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003744 FREE_AND_NULL(str)
3745
3746 if (bind == NULL)
3747 return;
3748 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003749 fprintf(output, "IDC: BINDING %s\n",
3750 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003751 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003752 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003753 for (i = 0; i < bind->nbNodes; i++) {
3754 tab = bind->nodeTable[i];
3755 fprintf(output, " ( ");
3756 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003757 key = tab->keys[j];
3758 if ((key != NULL) && (key->val != NULL)) {
3759 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003760 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003761 fprintf(output, "\"%s\" ", value);
3762 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003763 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003764 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003765 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003766 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003767 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003768 else
3769 fprintf(output, "(key missing), ");
3770 }
3771 fprintf(output, ")\n");
3772 }
3773 bind = bind->next;
3774 } while (bind != NULL);
3775}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003776#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003777#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003778
3779/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003780 * *
3781 * Utilities *
3782 * *
3783 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003784
Daniel Veillardc0826a72004-08-10 14:17:33 +00003785/**
3786 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003787 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003788 * @name: the name of the attribute
3789 *
3790 * Seeks an attribute with a name of @name in
3791 * no namespace.
3792 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003793 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003794 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003795static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003796xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003797{
3798 xmlAttrPtr prop;
3799
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003800 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003801 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003802 prop = node->properties;
3803 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003804 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003805 return(prop);
3806 prop = prop->next;
3807 }
3808 return (NULL);
3809}
3810
3811/**
3812 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003813 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003814 * @uri: the uri
3815 * @name: the name of the attribute
3816 *
3817 * Seeks an attribute with a local name of @name and
3818 * a namespace URI of @uri.
3819 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003820 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003821 */
3822static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003823xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003824{
3825 xmlAttrPtr prop;
3826
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003827 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003828 return(NULL);
3829 prop = node->properties;
3830 while (prop != NULL) {
3831 if ((prop->ns != NULL) &&
3832 xmlStrEqual(prop->name, BAD_CAST name) &&
3833 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003834 return(prop);
3835 prop = prop->next;
3836 }
3837 return (NULL);
3838}
3839
3840static const xmlChar *
3841xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3842{
3843 xmlChar *val;
3844 const xmlChar *ret;
3845
3846 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003847 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003848 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003849 ret = xmlDictLookup(ctxt->dict, val, -1);
3850 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003851 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003852}
3853
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003854/**
3855 * xmlSchemaGetProp:
3856 * @ctxt: the parser context
3857 * @node: the node
3858 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003859 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003860 * Read a attribute value and internalize the string
3861 *
3862 * Returns the string or NULL if not present.
3863 */
3864static const xmlChar *
3865xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3866 const char *name)
3867{
3868 xmlChar *val;
3869 const xmlChar *ret;
3870
3871 val = xmlGetProp(node, BAD_CAST name);
3872 if (val == NULL)
3873 return(NULL);
3874 ret = xmlDictLookup(ctxt->dict, val, -1);
3875 xmlFree(val);
3876 return(ret);
3877}
3878
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003879/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003880 * *
3881 * Parsing functions *
3882 * *
3883 ************************************************************************/
3884
3885/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003886 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003887 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003888 * @name: the element name
3889 * @ns: the element namespace
3890 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003891 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003892 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003893 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003894 */
3895static xmlSchemaElementPtr
3896xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003897 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003898{
3899 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003900
3901 if ((name == NULL) || (schema == NULL))
3902 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003903
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003904 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003905 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003906 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003907 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003908 } else
3909 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003910 /*
3911 * This one was removed, since top level element declarations have
3912 * the target namespace specified in targetNamespace of the <schema>
3913 * information element, even if elementFormDefault is "unqualified".
3914 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003915
William M. Bracke7091952004-05-11 15:09:58 +00003916 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003917 if (xmlStrEqual(namespace, schema->targetNamespace))
3918 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3919 else
3920 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003921 if ((ret != NULL) &&
3922 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003923 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003924 }
William M. Bracke7091952004-05-11 15:09:58 +00003925 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003926
William M. Brack2f2a6632004-08-20 23:09:47 +00003927 /*
3928 * Removed since imported components will be hold by the main schema only.
3929 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003930 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003931 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003932 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003933 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003934 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003935 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003936 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3937 return (ret);
3938 } else
3939 ret = NULL;
3940 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003941 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003942#ifdef DEBUG
3943 if (ret == NULL) {
3944 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003945 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003946 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003947 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003948 namespace);
3949 }
3950#endif
3951 return (ret);
3952}
3953
3954/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003955 * xmlSchemaGetType:
3956 * @schema: the schemas context
3957 * @name: the type name
3958 * @ns: the type namespace
3959 *
3960 * Lookup a type in the schemas or the predefined types
3961 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003962 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003963 */
3964static xmlSchemaTypePtr
3965xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003966 const xmlChar * namespace)
3967{
Daniel Veillard4255d502002-04-16 15:50:10 +00003968 xmlSchemaTypePtr ret;
3969
3970 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003971 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003972 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003973 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003974 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003975 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003976 }
3977 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003978 if (ret != NULL)
3979 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003980 /*
3981 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003982 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003983 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003984 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003985 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003986 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003987 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003988 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003989 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3990 return (ret);
3991 } else
3992 ret = NULL;
3993 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003994 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003995#ifdef DEBUG
3996 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003997 if (namespace == NULL)
3998 fprintf(stderr, "Unable to lookup type %s", name);
3999 else
4000 fprintf(stderr, "Unable to lookup type %s:%s", name,
4001 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004002 }
4003#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004004 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004005}
4006
Daniel Veillard3646d642004-06-02 19:19:14 +00004007/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004008 * xmlSchemaGetAttributeDecl:
4009 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004010 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004011 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004012 *
4013 * Lookup a an attribute in the schema or imported schemas
4014 *
4015 * Returns the attribute declaration or NULL if not found.
4016 */
4017static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004018xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004019 const xmlChar * namespace)
4020{
4021 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004022
4023 if ((name == NULL) || (schema == NULL))
4024 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004025
4026
Daniel Veillard3646d642004-06-02 19:19:14 +00004027 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4028 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004029 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004030 else
4031 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004032 /*
4033 * Removed, since imported components will be hold by the main schema only.
4034 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004035 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004036 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004037 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004038 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004039 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004040 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004041 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4042 return (ret);
4043 } else
4044 ret = NULL;
4045 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004046 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004047#ifdef DEBUG
4048 if (ret == NULL) {
4049 if (namespace == NULL)
4050 fprintf(stderr, "Unable to lookup attribute %s", name);
4051 else
4052 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4053 namespace);
4054 }
4055#endif
4056 return (ret);
4057}
4058
4059/**
4060 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004061 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004062 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004063 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004064 *
4065 * Lookup a an attribute group in the schema or imported schemas
4066 *
4067 * Returns the attribute group definition or NULL if not found.
4068 */
4069static xmlSchemaAttributeGroupPtr
4070xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4071 const xmlChar * namespace)
4072{
4073 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004074
4075 if ((name == NULL) || (schema == NULL))
4076 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004077
4078
Daniel Veillard3646d642004-06-02 19:19:14 +00004079 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4080 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004081 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004082 else
4083 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004084 /*
4085 * Removed since imported components will be hold by the main schema only.
4086 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004087 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004088 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004089 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004090 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004091 if (import != NULL) {
4092 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4093 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4094 return (ret);
4095 else
4096 ret = NULL;
4097 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004098 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004099#ifdef DEBUG
4100 if (ret == NULL) {
4101 if (namespace == NULL)
4102 fprintf(stderr, "Unable to lookup attribute group %s", name);
4103 else
4104 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4105 namespace);
4106 }
4107#endif
4108 return (ret);
4109}
4110
4111/**
4112 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004113 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004114 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004115 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004116 *
4117 * Lookup a group in the schema or imported schemas
4118 *
4119 * Returns the group definition or NULL if not found.
4120 */
4121static xmlSchemaTypePtr
4122xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4123 const xmlChar * namespace)
4124{
4125 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004126
4127 if ((name == NULL) || (schema == NULL))
4128 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004129
Daniel Veillard3646d642004-06-02 19:19:14 +00004130 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004131 /*
4132 * Removed since imported components will be hold by the main schema only.
4133 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004134 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004135 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004136 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004137 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004138 if (import != NULL) {
4139 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4140 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4141 return (ret);
4142 else
4143 ret = NULL;
4144 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004145 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004146#ifdef DEBUG
4147 if (ret == NULL) {
4148 if (namespace == NULL)
4149 fprintf(stderr, "Unable to lookup group %s", name);
4150 else
4151 fprintf(stderr, "Unable to lookup group %s:%s", name,
4152 namespace);
4153 }
4154#endif
4155 return (ret);
4156}
4157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004158/**
4159 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004160 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004161 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004162 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004163 *
4164 * Lookup a group in the schema or imported schemas
4165 *
4166 * Returns the group definition or NULL if not found.
4167 */
4168static xmlSchemaTreeItemPtr
4169xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4170 xmlSchemaTypeType itemType,
4171 const xmlChar *name,
4172 const xmlChar *targetNs)
4173{
4174 switch (itemType) {
4175 case XML_SCHEMA_TYPE_GROUP:
4176 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4177 name, targetNs));
4178 case XML_SCHEMA_TYPE_ELEMENT:
4179 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4180 name, targetNs));
4181 default:
4182 return (NULL);
4183 }
4184}
4185
Daniel Veillard4255d502002-04-16 15:50:10 +00004186/************************************************************************
4187 * *
4188 * Parsing functions *
4189 * *
4190 ************************************************************************/
4191
4192#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004193 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004194
4195/**
4196 * xmlSchemaIsBlank:
4197 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004198 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004199 *
4200 * Check if a string is ignorable
4201 *
4202 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4203 */
4204static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004205xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004206{
Daniel Veillard4255d502002-04-16 15:50:10 +00004207 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004208 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004209 if (len < 0) {
4210 while (*str != 0) {
4211 if (!(IS_BLANK_CH(*str)))
4212 return (0);
4213 str++;
4214 }
4215 } else while ((*str != 0) && (len != 0)) {
4216 if (!(IS_BLANK_CH(*str)))
4217 return (0);
4218 str++;
4219 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004220 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004221
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004222 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004223}
4224
4225/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004226 * xmlSchemaAddAssembledItem:
4227 * @ctxt: a schema parser context
4228 * @schema: the schema being built
4229 * @item: the item
4230 *
4231 * Add a item to the schema's list of current items.
4232 * This is used if the schema was already constructed and
4233 * new schemata need to be added to it.
4234 * *WARNING* this interface is highly subject to change.
4235 *
4236 * Returns 0 if suceeds and -1 if an internal error occurs.
4237 */
4238static int
4239xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4240 xmlSchemaTypePtr item)
4241{
4242 static int growSize = 100;
4243 xmlSchemaAssemblePtr ass;
4244
4245 ass = ctxt->assemble;
4246 if (ass->sizeItems < 0) {
4247 /* If disabled. */
4248 return (0);
4249 }
4250 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004251 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004252 if (ass->items == NULL) {
4253 xmlSchemaPErrMemory(ctxt,
4254 "allocating new item buffer", NULL);
4255 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004256 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004257 ass->sizeItems = growSize;
4258 } else if (ass->sizeItems <= ass->nbItems) {
4259 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004260 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004261 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4262 if (ass->items == NULL) {
4263 xmlSchemaPErrMemory(ctxt,
4264 "growing item buffer", NULL);
4265 ass->sizeItems = 0;
4266 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004267 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004268 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004269 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004270 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4271 return (0);
4272}
4273
4274/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004275 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004276 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004277 * @schema: the schema being built
4278 * @name: the item name
4279 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004280 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004281 * *WARNING* this interface is highly subject to change
4282 *
4283 * Returns the new struture or NULL in case of error
4284 */
4285static xmlSchemaNotationPtr
4286xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004287 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004288{
4289 xmlSchemaNotationPtr ret = NULL;
4290 int val;
4291
4292 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4293 return (NULL);
4294
4295 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004296 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 if (schema->notaDecl == NULL)
4298 return (NULL);
4299
4300 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4301 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004302 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004303 return (NULL);
4304 }
4305 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004306 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4308 ret);
4309 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004310 /*
4311 * TODO: This should never happen, since a unique name will be computed.
4312 * If it fails, then an other internal error must have occured.
4313 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004314 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4315 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004316 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004317 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004318 xmlFree(ret);
4319 return (NULL);
4320 }
4321 return (ret);
4322}
4323
4324
4325/**
4326 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004327 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 * @schema: the schema being built
4329 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004330 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004331 *
4332 * Add an XML schema Attrribute declaration
4333 * *WARNING* this interface is highly subject to change
4334 *
4335 * Returns the new struture or NULL in case of error
4336 */
4337static xmlSchemaAttributePtr
4338xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004339 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004340 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004341{
4342 xmlSchemaAttributePtr ret = NULL;
4343 int val;
4344
4345 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4346 return (NULL);
4347
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004348#ifdef DEBUG
4349 fprintf(stderr, "Adding attribute %s\n", name);
4350 if (namespace != NULL)
4351 fprintf(stderr, " target namespace %s\n", namespace);
4352#endif
4353
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004355 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004356 if (schema->attrDecl == NULL)
4357 return (NULL);
4358
4359 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4360 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004361 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004362 return (NULL);
4363 }
4364 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004365 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004366 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004367 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004368 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004369 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004370 if (topLevel) {
4371 xmlSchemaPCustomErr(ctxt,
4372 XML_SCHEMAP_REDEFINED_ATTR,
4373 NULL, NULL, node,
4374 "A global attribute declaration with the name '%s' does "
4375 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004376 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004377 return (NULL);
4378 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004379 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004380 /*
4381 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4382 * in the scenario:
4383 * 1. multiple top-level complex types have different target
4384 * namespaces but have the SAME NAME; this can happen if
4385 * schemata are imported
4386 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004387 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004388 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004389 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004390 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004391 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004392 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004393
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004394 if (val != 0) {
4395 xmlSchemaPCustomErr(ctxt,
4396 XML_SCHEMAP_INTERNAL,
4397 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004398 "Internal error: xmlSchemaAddAttribute, "
4399 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004400 "could not be added to the hash.", name);
4401 xmlFree(ret);
4402 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004403 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004404 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004405 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004406 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004407 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004408 return (ret);
4409}
4410
4411/**
4412 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004413 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004414 * @schema: the schema being built
4415 * @name: the item name
4416 *
4417 * Add an XML schema Attrribute Group declaration
4418 *
4419 * Returns the new struture or NULL in case of error
4420 */
4421static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004422xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004423 xmlSchemaPtr schema, const xmlChar * name,
4424 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004425{
4426 xmlSchemaAttributeGroupPtr ret = NULL;
4427 int val;
4428
4429 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4430 return (NULL);
4431
4432 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004433 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004434 if (schema->attrgrpDecl == NULL)
4435 return (NULL);
4436
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004437 ret =
4438 (xmlSchemaAttributeGroupPtr)
4439 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004441 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004442 return (NULL);
4443 }
4444 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004445 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004447 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004448 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004449 xmlSchemaPCustomErr(ctxt,
4450 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4451 NULL, NULL, node,
4452 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004453 xmlFree(ret);
4454 return (NULL);
4455 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004456 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004457 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 return (ret);
4459}
4460
4461/**
4462 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004463 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004464 * @schema: the schema being built
4465 * @name: the type name
4466 * @namespace: the type namespace
4467 *
4468 * Add an XML schema Element declaration
4469 * *WARNING* this interface is highly subject to change
4470 *
4471 * Returns the new struture or NULL in case of error
4472 */
4473static xmlSchemaElementPtr
4474xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004475 const xmlChar * name, const xmlChar * namespace,
4476 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004477{
4478 xmlSchemaElementPtr ret = NULL;
4479 int val;
4480
4481 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4482 return (NULL);
4483
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004484#ifdef DEBUG
4485 fprintf(stderr, "Adding element %s\n", name);
4486 if (namespace != NULL)
4487 fprintf(stderr, " target namespace %s\n", namespace);
4488#endif
4489
Daniel Veillard4255d502002-04-16 15:50:10 +00004490 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004491 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004492 if (schema->elemDecl == NULL)
4493 return (NULL);
4494
4495 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4496 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004497 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004498 return (NULL);
4499 }
4500 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004501 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004504 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004505 if (topLevel) {
4506 xmlSchemaPCustomErr(ctxt,
4507 XML_SCHEMAP_REDEFINED_ELEMENT,
4508 NULL, NULL, node,
4509 "A global element declaration with the name '%s' does "
4510 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004511 xmlFree(ret);
4512 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004513 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004514 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004515
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004516 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004517 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004518 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004519 if (val != 0) {
4520 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004521 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004522 NULL, NULL, node,
4523 "Internal error: xmlSchemaAddElement, "
4524 "a dublicate element declaration with the name '%s' "
4525 "could not be added to the hash.", name);
4526 xmlFree(ret);
4527 return (NULL);
4528 }
4529 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004530
Daniel Veillard4255d502002-04-16 15:50:10 +00004531 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004532 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004533 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004534 return (ret);
4535}
4536
4537/**
4538 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004539 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004540 * @schema: the schema being built
4541 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004542 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004543 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004544 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004545 * *WARNING* this interface is highly subject to change
4546 *
4547 * Returns the new struture or NULL in case of error
4548 */
4549static xmlSchemaTypePtr
4550xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004551 const xmlChar * name, const xmlChar * namespace,
4552 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004553{
4554 xmlSchemaTypePtr ret = NULL;
4555 int val;
4556
4557 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4558 return (NULL);
4559
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004560#ifdef DEBUG
4561 fprintf(stderr, "Adding type %s\n", name);
4562 if (namespace != NULL)
4563 fprintf(stderr, " target namespace %s\n", namespace);
4564#endif
4565
Daniel Veillard4255d502002-04-16 15:50:10 +00004566 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004567 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004568 if (schema->typeDecl == NULL)
4569 return (NULL);
4570
4571 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4572 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004573 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004574 return (NULL);
4575 }
4576 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004577 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004578 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004579 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004580 if (val != 0) {
4581 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004582 xmlSchemaPCustomErr(ctxt,
4583 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004584 NULL, NULL, node,
4585 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004586 xmlFree(ret);
4587 return (NULL);
4588 } else {
4589 xmlSchemaTypePtr prev;
4590
4591 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4592 if (prev == NULL) {
4593 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004594 XML_ERR_INTERNAL_ERROR,
4595 "Internal error: xmlSchemaAddType, on type "
4596 "'%s'.\n",
4597 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004598 xmlFree(ret);
4599 return (NULL);
4600 }
4601 ret->redef = prev->redef;
4602 prev->redef = ret;
4603 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004604 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004605 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004606 ret->minOccurs = 1;
4607 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004608 ret->attributeUses = NULL;
4609 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004610 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004611 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004612 return (ret);
4613}
4614
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004615static xmlSchemaQNameRefPtr
4616xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4617 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004618 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004619 const xmlChar *refNs)
4620{
4621 xmlSchemaQNameRefPtr ret;
4622
4623 ret = (xmlSchemaQNameRefPtr)
4624 xmlMalloc(sizeof(xmlSchemaQNameRef));
4625 if (ret == NULL) {
4626 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4627 NULL);
4628 return (NULL);
4629 }
4630 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4631 ret->name = refName;
4632 ret->targetNamespace = refNs;
4633 ret->item = NULL;
4634 ret->itemType = refType;
4635 /*
4636 * Store the reference item in the schema.
4637 */
4638 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4639 return (ret);
4640}
4641
4642/**
4643 * xmlSchemaAddModelGroup:
4644 * @ctxt: a schema parser context
4645 * @schema: the schema being built
4646 * @type: the "compositor" type of the model group
4647 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004648 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004649 *
4650 * Adds a schema model group
4651 * *WARNING* this interface is highly subject to change
4652 *
4653 * Returns the new struture or NULL in case of error
4654 */
4655static xmlSchemaModelGroupPtr
4656xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4657 xmlSchemaTypeType type, const xmlChar **container,
4658 xmlNodePtr node)
4659{
4660 xmlSchemaModelGroupPtr ret = NULL;
4661 xmlChar buf[30];
4662
4663 if ((ctxt == NULL) || (schema == NULL))
4664 return (NULL);
4665
4666#ifdef DEBUG
4667 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004668#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004669 ret = (xmlSchemaModelGroupPtr)
4670 xmlMalloc(sizeof(xmlSchemaModelGroup));
4671 if (ret == NULL) {
4672 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4673 NULL);
4674 return (NULL);
4675 }
4676 ret->type = type;
4677 ret->annot = NULL;
4678 ret->node = node;
4679 ret->children = NULL;
4680 ret->next = NULL;
4681 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4682 if (container != NULL)
4683 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4684 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004685 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004686 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4687 } else {
4688 if (container != NULL)
4689 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4690 }
4691 if (container != NULL)
4692 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4693 /*
4694 * Add to volatile items.
4695 * TODO: this should be changed someday.
4696 */
4697 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4698 xmlFree(ret);
4699 return (NULL);
4700 }
4701 return (ret);
4702}
4703
4704
4705/**
4706 * xmlSchemaAddParticle:
4707 * @ctxt: a schema parser context
4708 * @schema: the schema being built
4709 * @node: the corresponding node in the schema doc
4710 * @min: the minOccurs
4711 * @max: the maxOccurs
4712 *
4713 * Adds an XML schema particle component.
4714 * *WARNING* this interface is highly subject to change
4715 *
4716 * Returns the new struture or NULL in case of error
4717 */
4718static xmlSchemaParticlePtr
4719xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4720 xmlNodePtr node, int min, int max)
4721{
4722 xmlSchemaParticlePtr ret = NULL;
4723 if ((ctxt == NULL) || (schema == NULL))
4724 return (NULL);
4725
4726#ifdef DEBUG
4727 fprintf(stderr, "Adding particle component\n");
4728#endif
4729 ret = (xmlSchemaParticlePtr)
4730 xmlMalloc(sizeof(xmlSchemaParticle));
4731 if (ret == NULL) {
4732 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4733 NULL);
4734 return (NULL);
4735 }
4736 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4737 ret->annot = NULL;
4738 ret->node = node;
4739 ret->minOccurs = min;
4740 ret->maxOccurs = max;
4741 ret->next = NULL;
4742 ret->children = NULL;
4743
4744 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4745 xmlFree(ret);
4746 return (NULL);
4747 }
4748 return (ret);
4749}
4750
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004751/**
4752 * xmlSchemaAddGroup:
4753 * @ctxt: a schema validation context
4754 * @schema: the schema being built
4755 * @name: the group name
4756 *
4757 * Add an XML schema Group definition
4758 *
4759 * Returns the new struture or NULL in case of error
4760 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004761static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004762xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004763 const xmlChar *name, const xmlChar *namespaceName,
4764 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004766 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004767 int val;
4768
4769 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4770 return (NULL);
4771
4772 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004773 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004774 if (schema->groupDecl == NULL)
4775 return (NULL);
4776
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004777 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004778 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004779 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004780 return (NULL);
4781 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004782 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004783 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004784 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004785 ret->node = node;
4786 ret->targetNamespace = namespaceName;
4787 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004788 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004789 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004790 XML_SCHEMAP_REDEFINED_GROUP,
4791 NULL, NULL, node,
4792 "A global model group definition with the name '%s' does already "
4793 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004794 xmlFree(ret);
4795 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004796 }
4797 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004798 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004799 return (ret);
4800}
4801
Daniel Veillard3646d642004-06-02 19:19:14 +00004802/**
4803 * xmlSchemaNewWildcardNs:
4804 * @ctxt: a schema validation context
4805 *
4806 * Creates a new wildcard namespace constraint.
4807 *
4808 * Returns the new struture or NULL in case of error
4809 */
4810static xmlSchemaWildcardNsPtr
4811xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4812{
4813 xmlSchemaWildcardNsPtr ret;
4814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004815 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004816 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4817 if (ret == NULL) {
4818 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004819 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004820 }
4821 ret->value = NULL;
4822 ret->next = NULL;
4823 return (ret);
4824}
4825
4826/**
4827 * xmlSchemaAddWildcard:
4828 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004829 * @schema: a schema
4830 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004831 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004832 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004833 *
4834 * Returns the new struture or NULL in case of error
4835 */
4836static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004837xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4838 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004839{
4840 xmlSchemaWildcardPtr ret = NULL;
4841
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004842 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004843 return (NULL);
4844
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004845#ifdef DEBUG
4846 fprintf(stderr, "Adding wildcard component\n");
4847#endif
4848
Daniel Veillard3646d642004-06-02 19:19:14 +00004849 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4850 if (ret == NULL) {
4851 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4852 return (NULL);
4853 }
4854 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004855 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004856 ret->minOccurs = 1;
4857 ret->maxOccurs = 1;
4858
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004859 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4860 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4861 "Failed to add a wildcard component to the list", NULL);
4862 xmlFree(ret);
4863 return (NULL);
4864 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004865 return (ret);
4866}
4867
Daniel Veillard4255d502002-04-16 15:50:10 +00004868/************************************************************************
4869 * *
4870 * Utilities for parsing *
4871 * *
4872 ************************************************************************/
4873
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004874#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004875/**
4876 * xmlGetQNameProp:
4877 * @ctxt: a schema validation context
4878 * @node: a subtree containing XML Schema informations
4879 * @name: the attribute name
4880 * @namespace: the result namespace if any
4881 *
4882 * Extract a QName Attribute value
4883 *
4884 * Returns the NCName or NULL if not found, and also update @namespace
4885 * with the namespace URI
4886 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004887static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004888xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004889 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004890{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004891 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004892 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004893 const xmlChar *ret, *prefix;
4894 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004895 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004896
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004897 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004898 attr = xmlSchemaGetPropNode(node, name);
4899 if (attr == NULL)
4900 return (NULL);
4901 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004902
Daniel Veillard4255d502002-04-16 15:50:10 +00004903 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004904 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004905
Daniel Veillardba0153a2004-04-01 10:42:31 +00004906 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004907 ns = xmlSearchNs(node->doc, node, 0);
4908 if (ns) {
4909 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4910 return (val);
4911 }
4912 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004913 ret = xmlSplitQName3(val, &len);
4914 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004915 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004916 }
4917 ret = xmlDictLookup(ctxt->dict, ret, -1);
4918 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004919
4920 ns = xmlSearchNs(node->doc, node, prefix);
4921 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004922 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4923 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004924 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004925 "The QName value '%s' has no corresponding namespace "
4926 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004927 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004928 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004929 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004930 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004931}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004932#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004933
4934/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004935 * xmlSchemaPValAttrNodeQNameValue:
4936 * @ctxt: a schema parser context
4937 * @schema: the schema context
4938 * @ownerDes: the designation of the parent element
4939 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004940 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004941 * @local: the resulting local part if found, the attribute value otherwise
4942 * @uri: the resulting namespace URI if found
4943 *
4944 * Extracts the local name and the URI of a QName value and validates it.
4945 * This one is intended to be used on attribute values that
4946 * should resolve to schema components.
4947 *
4948 * Returns 0, in case the QName is valid, a positive error code
4949 * if not valid and -1 if an internal error occurs.
4950 */
4951static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004952xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004953 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004954 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004955 xmlSchemaTypePtr ownerItem,
4956 xmlAttrPtr attr,
4957 const xmlChar *value,
4958 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004959 const xmlChar **local)
4960{
4961 const xmlChar *pref;
4962 xmlNsPtr ns;
4963 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004964
Daniel Veillardc0826a72004-08-10 14:17:33 +00004965 *uri = NULL;
4966 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004967 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004968 if (ret > 0) {
4969 xmlSchemaPSimpleTypeErr(ctxt,
4970 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4971 ownerItem, (xmlNodePtr) attr,
4972 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4973 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004974 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004975 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004976 } else if (ret < 0)
4977 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004978
4979 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004980 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4981 if (ns)
4982 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4983 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4984 /*
4985 * This one takes care of included schemas with no
4986 * target namespace.
4987 */
4988 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004989 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004990 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 return (0);
4992 }
4993 /*
4994 * At this point xmlSplitQName3 has to return a local name.
4995 */
4996 *local = xmlSplitQName3(value, &len);
4997 *local = xmlDictLookup(ctxt->dict, *local, -1);
4998 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004999 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5000 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005001 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005002 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005003 ownerItem, (xmlNodePtr) attr,
5004 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5005 "The value '%s' of simple type 'xs:QName' has no "
5006 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005007 return (ctxt->err);
5008 } else {
5009 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005010 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005011 return (0);
5012}
5013
5014/**
5015 * xmlSchemaPValAttrNodeQName:
5016 * @ctxt: a schema parser context
5017 * @schema: the schema context
5018 * @ownerDes: the designation of the owner element
5019 * @ownerItem: the owner as a schema object
5020 * @attr: the attribute node
5021 * @local: the resulting local part if found, the attribute value otherwise
5022 * @uri: the resulting namespace URI if found
5023 *
5024 * Extracts and validates the QName of an attribute value.
5025 * This one is intended to be used on attribute values that
5026 * should resolve to schema components.
5027 *
5028 * Returns 0, in case the QName is valid, a positive error code
5029 * if not valid and -1 if an internal error occurs.
5030 */
5031static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005032xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005033 xmlSchemaPtr schema,
5034 xmlChar **ownerDes,
5035 xmlSchemaTypePtr ownerItem,
5036 xmlAttrPtr attr,
5037 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005038 const xmlChar **local)
5039{
5040 const xmlChar *value;
5041
5042 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005043 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5044 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005045}
5046
5047/**
5048 * xmlSchemaPValAttrQName:
5049 * @ctxt: a schema parser context
5050 * @schema: the schema context
5051 * @ownerDes: the designation of the parent element
5052 * @ownerItem: the owner as a schema object
5053 * @ownerElem: the parent node of the attribute
5054 * @name: the name of the attribute
5055 * @local: the resulting local part if found, the attribute value otherwise
5056 * @uri: the resulting namespace URI if found
5057 *
5058 * Extracts and validates the QName of an attribute value.
5059 *
5060 * Returns 0, in case the QName is valid, a positive error code
5061 * if not valid and -1 if an internal error occurs.
5062 */
5063static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005064xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5065 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005066 xmlChar **ownerDes,
5067 xmlSchemaTypePtr ownerItem,
5068 xmlNodePtr ownerElem,
5069 const char *name,
5070 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005071 const xmlChar **local)
5072{
5073 xmlAttrPtr attr;
5074
5075 attr = xmlSchemaGetPropNode(ownerElem, name);
5076 if (attr == NULL) {
5077 *local = NULL;
5078 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005079 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005080 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005081 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5082 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005083}
5084
5085/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005086 * xmlSchemaPValAttrID:
5087 * @ctxt: a schema parser context
5088 * @schema: the schema context
5089 * @ownerDes: the designation of the parent element
5090 * @ownerItem: the owner as a schema object
5091 * @ownerElem: the parent node of the attribute
5092 * @name: the name of the attribute
5093 *
5094 * Extracts and validates the ID of an attribute value.
5095 *
5096 * Returns 0, in case the ID is valid, a positive error code
5097 * if not valid and -1 if an internal error occurs.
5098 */
5099static int
5100xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005101 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005102 xmlSchemaTypePtr ownerItem,
5103 xmlNodePtr ownerElem,
5104 const xmlChar *name)
5105{
5106 int ret;
5107 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005108 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005109
5110 value = xmlGetNoNsProp(ownerElem, name);
5111 if (value == NULL)
5112 return (0);
5113
5114 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5115 if (attr == NULL)
5116 return (-1);
5117
5118 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005119 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005120 /*
5121 * NOTE: the IDness might have already be declared in the DTD
5122 */
5123 if (attr->atype != XML_ATTRIBUTE_ID) {
5124 xmlIDPtr res;
5125 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005126
5127 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005128 * TODO: Use xmlSchemaStrip here; it's not exported at this
5129 * moment.
5130 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005131 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005132 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005133 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005134 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5135 if (res == NULL) {
5136 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005137 xmlSchemaPSimpleTypeErr(ctxt,
5138 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5139 ownerItem, (xmlNodePtr) attr,
5140 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5141 NULL, NULL, "Duplicate value '%s' of simple "
5142 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005143 } else
5144 attr->atype = XML_ATTRIBUTE_ID;
5145 if (strip != NULL)
5146 xmlFree(strip);
5147 }
5148 } else if (ret > 0) {
5149 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005150 xmlSchemaPSimpleTypeErr(ctxt,
5151 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5152 ownerItem, (xmlNodePtr) attr,
5153 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5154 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5155 "not a valid 'xs:NCName'",
5156 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005157 }
5158 xmlFree(value);
5159
5160 return (ret);
5161}
5162
5163/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005164 * xmlGetMaxOccurs:
5165 * @ctxt: a schema validation context
5166 * @node: a subtree containing XML Schema informations
5167 *
5168 * Get the maxOccurs property
5169 *
5170 * Returns the default if not found, or the value
5171 */
5172static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005173xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5174 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005175{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005176 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005177 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005178 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005179
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005180 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5181 if (attr == NULL)
5182 return (def);
5183 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005184
5185 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005186 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005187 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005188 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5189 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005190 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005191 val, NULL, NULL, NULL);
5192 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005193 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005194 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005195 }
5196
5197 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005198 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005199 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005200 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005201 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005202 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5203 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005204 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005205 val, NULL, NULL, NULL);
5206 return (def);
5207 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005208 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005209 ret = ret * 10 + (*cur - '0');
5210 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005211 }
William M. Brack76e95df2003-10-18 16:20:14 +00005212 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005213 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005214 /*
5215 * TODO: Restrict the maximal value to Integer.
5216 */
5217 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005218 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005219 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5220 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005221 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005222 val, NULL, NULL, NULL);
5223 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005224 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005225 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005226}
5227
5228/**
5229 * xmlGetMinOccurs:
5230 * @ctxt: a schema validation context
5231 * @node: a subtree containing XML Schema informations
5232 *
5233 * Get the minOccurs property
5234 *
5235 * Returns the default if not found, or the value
5236 */
5237static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005238xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005239 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005240{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005241 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005242 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005243 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005244
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005245 attr = xmlSchemaGetPropNode(node, "minOccurs");
5246 if (attr == NULL)
5247 return (def);
5248 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005250 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005251 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005252 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005253 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005254 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5255 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005256 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005257 val, NULL, NULL, NULL);
5258 return (def);
5259 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005260 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 ret = ret * 10 + (*cur - '0');
5262 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005263 }
William M. Brack76e95df2003-10-18 16:20:14 +00005264 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005265 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005266 /*
5267 * TODO: Restrict the maximal value to Integer.
5268 */
5269 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005270 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005271 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5272 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005273 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005274 val, NULL, NULL, NULL);
5275 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005276 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005277 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005278}
5279
5280/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005281 * xmlSchemaPGetBoolNodeValue:
5282 * @ctxt: a schema validation context
5283 * @ownerDes: owner designation
5284 * @ownerItem: the owner as a schema item
5285 * @node: the node holding the value
5286 *
5287 * Converts a boolean string value into 1 or 0.
5288 *
5289 * Returns 0 or 1.
5290 */
5291static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005292xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5293 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005294 xmlSchemaTypePtr ownerItem,
5295 xmlNodePtr node)
5296{
5297 xmlChar *value = NULL;
5298 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005299
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005300 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005301 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005302 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005303 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005304 * can have the following legal literals {true, false, 1, 0}.
5305 */
5306 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5307 res = 1;
5308 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5309 res = 0;
5310 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5311 res = 1;
5312 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005313 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005314 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005315 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005316 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005317 ownerItem, node,
5318 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5319 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005320 NULL, NULL, NULL);
5321 }
5322 if (value != NULL)
5323 xmlFree(value);
5324 return (res);
5325}
5326
5327/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005328 * xmlGetBooleanProp:
5329 * @ctxt: a schema validation context
5330 * @node: a subtree containing XML Schema informations
5331 * @name: the attribute name
5332 * @def: the default value
5333 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005334 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005335 *
5336 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005337 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 */
5339static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005340xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5341 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005342 xmlSchemaTypePtr ownerItem,
5343 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005344 const char *name, int def)
5345{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005346 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005347
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005348 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005349 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005350 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005351 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005353 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005354 * can have the following legal literals {true, false, 1, 0}.
5355 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005356 if (xmlStrEqual(val, BAD_CAST "true"))
5357 def = 1;
5358 else if (xmlStrEqual(val, BAD_CAST "false"))
5359 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005360 else if (xmlStrEqual(val, BAD_CAST "1"))
5361 def = 1;
5362 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005363 def = 0;
5364 else {
5365 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005366 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005367 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005368 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005369 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5370 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005371 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005372 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005373}
5374
5375/************************************************************************
5376 * *
5377 * Shema extraction from an Infoset *
5378 * *
5379 ************************************************************************/
5380static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5381 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005382 xmlNodePtr node,
5383 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005384static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5385 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005386 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005387 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005388 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005389static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5390 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005391 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005392 xmlNodePtr node,
5393 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005394static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5395 ctxt,
5396 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005397 xmlNodePtr node,
5398 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005399static xmlSchemaAttributeGroupPtr
5400xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005401 xmlSchemaPtr schema, xmlNodePtr node,
5402 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005403static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5404 xmlSchemaPtr schema,
5405 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005406static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005407xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5408 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005409
5410/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005411 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005412 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005413 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005414 * @ownerDes: the designation of the parent element
5415 * @ownerItem: the schema object owner if existent
5416 * @attr: the schema attribute node being validated
5417 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005418 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005419 *
5420 * Validates a value against the given built-in type.
5421 * This one is intended to be used internally for validation
5422 * of schema attribute values during parsing of the schema.
5423 *
5424 * Returns 0 if the value is valid, a positive error code
5425 * number otherwise and -1 in case of an internal or API error.
5426 */
5427static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005428xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5429 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5430 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005431 xmlAttrPtr attr,
5432 const xmlChar *value,
5433 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005434{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005435
5436 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005437
5438 /*
5439 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5440 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005441 */
5442 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005443 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005444 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5445 PERROR_INT("xmlSchemaPValAttrNodeValue",
5446 "the given type is not a built-in type");
5447 return (-1);
5448 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005449 switch (type->builtInType) {
5450 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005451 case XML_SCHEMAS_QNAME:
5452 case XML_SCHEMAS_ANYURI:
5453 case XML_SCHEMAS_TOKEN:
5454 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005455 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5456 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005457 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005458 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005459 PERROR_INT("xmlSchemaPValAttrNodeValue",
5460 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005461 return (-1);
5462 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005463 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005464 /*
5465 * TODO: Should we use the S4S error codes instead?
5466 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005467 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005468 PERROR_INT("xmlSchemaPValAttrNodeValue",
5469 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005470 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005471 } else if (ret > 0) {
5472 if (VARIETY_LIST(type))
5473 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5474 else
5475 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5476 xmlSchemaPSimpleTypeErr(pctxt,
5477 ret, ownerItem, (xmlNodePtr) attr,
5478 type, NULL, value, NULL, NULL, NULL);
5479 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005480 return (ret);
5481}
5482
5483/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005484 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005485 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005486 * @ctxt: a schema parser context
5487 * @ownerDes: the designation of the parent element
5488 * @ownerItem: the schema object owner if existent
5489 * @attr: the schema attribute node being validated
5490 * @type: the built-in type to be validated against
5491 * @value: the resulting value if any
5492 *
5493 * Extracts and validates a value against the given built-in type.
5494 * This one is intended to be used internally for validation
5495 * of schema attribute values during parsing of the schema.
5496 *
5497 * Returns 0 if the value is valid, a positive error code
5498 * number otherwise and -1 in case of an internal or API error.
5499 */
5500static int
5501xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5502 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005503 xmlSchemaTypePtr ownerItem,
5504 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005505 xmlSchemaTypePtr type,
5506 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005507{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005508 const xmlChar *val;
5509
5510 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005511 return (-1);
5512
Daniel Veillardc0826a72004-08-10 14:17:33 +00005513 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5514 if (value != NULL)
5515 *value = val;
5516
5517 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005518 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005519}
5520
5521/**
5522 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005523 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005524 * @ctxt: a schema parser context
5525 * @node: the element node of the attribute
5526 * @ownerDes: the designation of the parent element
5527 * @ownerItem: the schema object owner if existent
5528 * @ownerElem: the owner element node
5529 * @name: the name of the schema attribute node
5530 * @type: the built-in type to be validated against
5531 * @value: the resulting value if any
5532 *
5533 * Extracts and validates a value against the given built-in type.
5534 * This one is intended to be used internally for validation
5535 * of schema attribute values during parsing of the schema.
5536 *
5537 * Returns 0 if the value is valid, a positive error code
5538 * number otherwise and -1 in case of an internal or API error.
5539 */
5540static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005541xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005542 xmlChar **ownerDes,
5543 xmlSchemaTypePtr ownerItem,
5544 xmlNodePtr ownerElem,
5545 const char *name,
5546 xmlSchemaTypePtr type,
5547 const xmlChar **value)
5548{
5549 xmlAttrPtr attr;
5550
5551 if ((ctxt == NULL) || (type == NULL)) {
5552 if (value != NULL)
5553 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005554 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005555 }
5556 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5557 if (value != NULL)
5558 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005559 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005560 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 "Internal error: xmlSchemaPValAttr, the given "
5562 "type '%s' is not a built-in type.\n",
5563 type->name, NULL);
5564 return (-1);
5565 }
5566 attr = xmlSchemaGetPropNode(ownerElem, name);
5567 if (attr == NULL) {
5568 if (value != NULL)
5569 *value = NULL;
5570 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005571 }
5572 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005573 type, value));
5574}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005575
5576static int
5577xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5578 xmlSchemaPtr schema,
5579 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005580 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005581 const xmlChar *namespaceName)
5582{
5583 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005584 return (1);
5585 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5586 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005587 if (pctxt->localImports != NULL) {
5588 int i;
5589 for (i = 0; i < pctxt->nbLocalImports; i++)
5590 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5591 return (1);
5592 }
5593 if (namespaceName == NULL)
5594 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005595 NULL, (xmlSchemaTypePtr) item, node,
5596 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005597 "namespace are not valid, since not indicated by an import "
5598 "statement", NULL);
5599 else
5600 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005601 NULL, (xmlSchemaTypePtr) item, node,
5602 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005603 "namespace '%s' are not valid, since not indicated by an import "
5604 "statement", namespaceName);
5605 return (0);
5606}
5607
Daniel Veillardc0826a72004-08-10 14:17:33 +00005608/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 * xmlSchemaParseAttrDecls:
5610 * @ctxt: a schema validation context
5611 * @schema: the schema being built
5612 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005613 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005614 *
5615 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005616 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005617 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5618 */
5619static xmlNodePtr
5620xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5621 xmlNodePtr child, xmlSchemaTypePtr type)
5622{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005623 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005624
Daniel Veillard4255d502002-04-16 15:50:10 +00005625 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626 (IS_SCHEMA(child, "attributeGroup"))) {
5627 attr = NULL;
5628 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005629 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005630 } else if (IS_SCHEMA(child, "attributeGroup")) {
5631 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005632 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005633 }
5634 if (attr != NULL) {
5635 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005636 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5637 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5638 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005639 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005640 lastattr = attr;
5641 } else {
5642 lastattr->next = attr;
5643 lastattr = attr;
5644 }
5645 }
5646 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005647 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005648 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005649}
5650
5651/**
5652 * xmlSchemaParseAnnotation:
5653 * @ctxt: a schema validation context
5654 * @schema: the schema being built
5655 * @node: a subtree containing XML Schema informations
5656 *
5657 * parse a XML schema Attrribute declaration
5658 * *WARNING* this interface is highly subject to change
5659 *
William M. Bracke7091952004-05-11 15:09:58 +00005660 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 * 1 in case of success.
5662 */
5663static xmlSchemaAnnotPtr
5664xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5665 xmlNodePtr node)
5666{
5667 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005668 xmlNodePtr child = NULL;
5669 xmlAttrPtr attr;
5670 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005671
Daniel Veillardc0826a72004-08-10 14:17:33 +00005672 /*
5673 * INFO: S4S completed.
5674 */
5675 /*
5676 * id = ID
5677 * {any attributes with non-schema namespace . . .}>
5678 * Content: (appinfo | documentation)*
5679 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005680 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5681 return (NULL);
5682 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005683 attr = node->properties;
5684 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005685 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005686 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005687 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005688 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005689
5690 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005691 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5692 NULL, NULL, attr);
5693 }
5694 attr = attr->next;
5695 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005696 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005697 /*
5698 * And now for the children...
5699 */
5700 child = node->children;
5701 while (child != NULL) {
5702 if (IS_SCHEMA(child, "appinfo")) {
5703 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005704 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005705 * source = anyURI
5706 * {any attributes with non-schema namespace . . .}>
5707 * Content: ({any})*
5708 */
5709 attr = child->properties;
5710 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005711 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005712 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005713 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005714 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005715
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005716 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005717 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5718 NULL, NULL, attr);
5719 }
5720 attr = attr->next;
5721 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005722 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5723 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 child = child->next;
5725 } else if (IS_SCHEMA(child, "documentation")) {
5726 /* TODO: make available the content of "documentation". */
5727 /*
5728 * source = anyURI
5729 * {any attributes with non-schema namespace . . .}>
5730 * Content: ({any})*
5731 */
5732 attr = child->properties;
5733 while (attr != NULL) {
5734 if (attr->ns == NULL) {
5735 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005736 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005737 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5738 NULL, NULL, attr);
5739 }
5740 } else {
5741 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5742 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5743 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005744
5745 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005746 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5747 NULL, NULL, attr);
5748 }
5749 }
5750 attr = attr->next;
5751 }
5752 /*
5753 * Attribute "xml:lang".
5754 */
5755 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5756 if (attr != NULL)
5757 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005758 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005759 child = child->next;
5760 } else {
5761 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005762 xmlSchemaPContentErr(ctxt,
5763 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005764 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5765 barked = 1;
5766 child = child->next;
5767 }
5768 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005769
Daniel Veillard4255d502002-04-16 15:50:10 +00005770 return (ret);
5771}
5772
5773/**
5774 * xmlSchemaParseFacet:
5775 * @ctxt: a schema validation context
5776 * @schema: the schema being built
5777 * @node: a subtree containing XML Schema informations
5778 *
5779 * parse a XML schema Facet declaration
5780 * *WARNING* this interface is highly subject to change
5781 *
5782 * Returns the new type structure or NULL in case of error
5783 */
5784static xmlSchemaFacetPtr
5785xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005786 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005787{
5788 xmlSchemaFacetPtr facet;
5789 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005790 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005791
5792 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5793 return (NULL);
5794
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005795 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005796 if (facet == NULL) {
5797 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5798 return (NULL);
5799 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005800 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005801 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005802 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005803 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5804 "Facet %s has no value\n", node->name, NULL);
5805 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005806 return (NULL);
5807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005810 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005811 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005812 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005813 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005814 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005815 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005816 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005817 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005818 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005819 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005820 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005821 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005822 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005823 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005825 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005826 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005827 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5830 } else if (IS_SCHEMA(node, "minLength")) {
5831 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5832 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005833 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5834 "Unknown facet type %s\n", node->name, NULL);
5835 xmlSchemaFreeFacet(facet);
5836 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005837 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005838 xmlSchemaPValAttrID(ctxt, NULL,
5839 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005840 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005841 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5842 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5843 const xmlChar *fixed;
5844
5845 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5846 if (fixed != NULL) {
5847 if (xmlStrEqual(fixed, BAD_CAST "true"))
5848 facet->fixed = 1;
5849 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005850 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005851 child = node->children;
5852
5853 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005854 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5855 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005856 }
5857 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005858 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5859 "Facet %s has unexpected child content\n",
5860 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005861 }
5862 return (facet);
5863}
5864
5865/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005866 * xmlSchemaParseWildcardNs:
5867 * @ctxt: a schema parser context
5868 * @wildc: the wildcard, already created
5869 * @node: a subtree containing XML Schema informations
5870 *
5871 * Parses the attribute "processContents" and "namespace"
5872 * of a xsd:anyAttribute and xsd:any.
5873 * *WARNING* this interface is highly subject to change
5874 *
5875 * Returns 0 if everything goes fine, a positive error code
5876 * if something is not valid and -1 if an internal error occurs.
5877 */
5878static int
5879xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5880 xmlSchemaPtr schema,
5881 xmlSchemaWildcardPtr wildc,
5882 xmlNodePtr node)
5883{
5884 const xmlChar *pc, *ns, *dictnsItem;
5885 int ret = 0;
5886 xmlChar *nsItem;
5887 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5888 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005889
Daniel Veillardc0826a72004-08-10 14:17:33 +00005890 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5891 if ((pc == NULL)
5892 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5893 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5894 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5895 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5896 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5897 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5898 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005899 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005900 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005901 NULL, node,
5902 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005903 NULL, NULL, NULL);
5904 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005905 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005906 }
5907 /*
5908 * Build the namespace constraints.
5909 */
5910 attr = xmlSchemaGetPropNode(node, "namespace");
5911 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005912 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005913 wildc->any = 1;
5914 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5915 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005916 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005917 return (-1);
5918 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005919 wildc->negNsSet->value = schema->targetNamespace;
5920 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005921 const xmlChar *end, *cur;
5922
5923 cur = ns;
5924 do {
5925 while (IS_BLANK_CH(*cur))
5926 cur++;
5927 end = cur;
5928 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5929 end++;
5930 if (end == cur)
5931 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005932 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005933 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5934 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005935 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005936 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005937 NULL, (xmlNodePtr) attr,
5938 NULL,
5939 "((##any | ##other) | List of (xs:anyURI | "
5940 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005941 nsItem, NULL, NULL, NULL);
5942 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5943 } else {
5944 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5945 dictnsItem = schema->targetNamespace;
5946 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5947 dictnsItem = NULL;
5948 } else {
5949 /*
5950 * Validate the item (anyURI).
5951 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005952 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005953 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5954 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5955 }
5956 /*
5957 * Avoid dublicate namespaces.
5958 */
5959 tmp = wildc->nsSet;
5960 while (tmp != NULL) {
5961 if (dictnsItem == tmp->value)
5962 break;
5963 tmp = tmp->next;
5964 }
5965 if (tmp == NULL) {
5966 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5967 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005968 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005969 return (-1);
5970 }
5971 tmp->value = dictnsItem;
5972 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005973 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005974 wildc->nsSet = tmp;
5975 else
5976 lastNs->next = tmp;
5977 lastNs = tmp;
5978 }
5979
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005980 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005981 xmlFree(nsItem);
5982 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005983 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005984 }
5985 return (ret);
5986}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005987
5988static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005989xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5990 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005991 xmlNodePtr node,
5992 int minOccurs,
5993 int maxOccurs) {
5994
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005995 if ((maxOccurs == 0) && ( minOccurs == 0))
5996 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997 if (maxOccurs != UNBOUNDED) {
5998 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005999 * TODO: Maybe we should better not create the particle,
6000 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006001 * content model.
6002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006003 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006004 * 3.9.6 Schema Component Constraint: Particle Correct
6005 *
6006 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006007 if (maxOccurs < 1) {
6008 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006009 * 2.2 {max occurs} must be greater than or equal to 1.
6010 */
6011 xmlSchemaPCustomAttrErr(ctxt,
6012 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006013 NULL, NULL,
6014 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006015 "The value must be greater than or equal to 1");
6016 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6017 } else if (minOccurs > maxOccurs) {
6018 /*
6019 * 2.1 {min occurs} must not be greater than {max occurs}.
6020 */
6021 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006022 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006023 NULL, NULL,
6024 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006025 "The value must not be greater than the value of 'maxOccurs'");
6026 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006028 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006029 return (0);
6030}
6031
Daniel Veillardc0826a72004-08-10 14:17:33 +00006032/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 * xmlSchemaParseAny:
6034 * @ctxt: a schema validation context
6035 * @schema: the schema being built
6036 * @node: a subtree containing XML Schema informations
6037 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006038 * Parsea a XML schema <any> element. A particle and wildcard
6039 * will be created (except if minOccurs==maxOccurs==0, in this case
6040 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006041 * *WARNING* this interface is highly subject to change
6042 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006043 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006044 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006045static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006046xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6047 xmlNodePtr node)
6048{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006049 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006050 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006051 xmlSchemaWildcardPtr wild;
6052 int min, max;
6053 xmlAttrPtr attr;
6054 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006055
6056 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6057 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006058 /*
6059 * Check for illegal attributes.
6060 */
6061 attr = node->properties;
6062 while (attr != NULL) {
6063 if (attr->ns == NULL) {
6064 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6065 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6066 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6067 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6068 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006069 xmlSchemaPIllegalAttrErr(ctxt,
6070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6071 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006072 }
6073 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006074 xmlSchemaPIllegalAttrErr(ctxt,
6075 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6076 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006077 }
6078 attr = attr->next;
6079 }
6080 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6081 /*
6082 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006083 */
6084 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6085 "(xs:nonNegativeInteger | unbounded)");
6086 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6087 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006088 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6089 /*
6090 * Create & parse the wildcard.
6091 */
6092 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6093 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006094 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006095 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006096 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006097 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006098 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006099 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006100 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006101 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006102 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006103 }
6104 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006105 xmlSchemaPContentErr(ctxt,
6106 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006107 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006108 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006109 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006110 /*
6111 * No component if minOccurs==maxOccurs==0.
6112 */
6113 if ((min == 0) && (max == 0)) {
6114 /* Don't free the wildcard, since it's already on the list. */
6115 return (NULL);
6116 }
6117 /*
6118 * Create the particle.
6119 */
6120 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6121 if (particle == NULL)
6122 return (NULL);
6123 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006124 wild->minOccurs = min;
6125 wild->maxOccurs = max;
6126 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006127
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006128 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006129}
6130
6131/**
6132 * xmlSchemaParseNotation:
6133 * @ctxt: a schema validation context
6134 * @schema: the schema being built
6135 * @node: a subtree containing XML Schema informations
6136 *
6137 * parse a XML schema Notation declaration
6138 *
6139 * Returns the new structure or NULL in case of error
6140 */
6141static xmlSchemaNotationPtr
6142xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006143 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006144{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006145 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006146 xmlSchemaNotationPtr ret;
6147 xmlNodePtr child = NULL;
6148
6149 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6150 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006151 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006152 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006153 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6154 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006155 return (NULL);
6156 }
6157 ret = xmlSchemaAddNotation(ctxt, schema, name);
6158 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006159 return (NULL);
6160 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006161 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006162
6163 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6164 node, BAD_CAST "id");
6165
6166 if (IS_SCHEMA(child, "annotation")) {
6167 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6168 child = child->next;
6169 }
6170
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 child = node->children;
6172 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006173 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6174 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006175 }
6176 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006177 xmlSchemaPContentErr(ctxt,
6178 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006179 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006180 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006181 }
6182
6183 return (ret);
6184}
6185
6186/**
6187 * xmlSchemaParseAnyAttribute:
6188 * @ctxt: a schema validation context
6189 * @schema: the schema being built
6190 * @node: a subtree containing XML Schema informations
6191 *
6192 * parse a XML schema AnyAttrribute declaration
6193 * *WARNING* this interface is highly subject to change
6194 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006195 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006196 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006197static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006198xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6199 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006200{
Daniel Veillard3646d642004-06-02 19:19:14 +00006201 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006203 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006204
6205 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6206 return (NULL);
6207
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006208 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6209 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006210 if (ret == NULL) {
6211 return (NULL);
6212 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006213 /*
6214 * Check for illegal attributes.
6215 */
6216 attr = node->properties;
6217 while (attr != NULL) {
6218 if (attr->ns == NULL) {
6219 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6220 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6221 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006222 xmlSchemaPIllegalAttrErr(ctxt,
6223 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6224 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006225 }
6226 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006227 xmlSchemaPIllegalAttrErr(ctxt,
6228 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6229 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006230 }
6231 attr = attr->next;
6232 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006233 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6234 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006235 /*
6236 * Parse the namespace list.
6237 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006238 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006239 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006240 /*
6241 * And now for the children...
6242 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006243 child = node->children;
6244 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006245 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6246 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006247 }
6248 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006249 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006250 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006251 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006252 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006253 }
6254
6255 return (ret);
6256}
6257
6258
6259/**
6260 * xmlSchemaParseAttribute:
6261 * @ctxt: a schema validation context
6262 * @schema: the schema being built
6263 * @node: a subtree containing XML Schema informations
6264 *
6265 * parse a XML schema Attrribute declaration
6266 * *WARNING* this interface is highly subject to change
6267 *
William M. Bracke7091952004-05-11 15:09:58 +00006268 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006269 */
6270static xmlSchemaAttributePtr
6271xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006272 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006273{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006274 const xmlChar *name, *attrValue;
6275 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006276 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006277 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006278 xmlAttrPtr attr, nameAttr;
6279 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006280
6281 /*
6282 * Note that the w3c spec assumes the schema to be validated with schema
6283 * for schemas beforehand.
6284 *
6285 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006286 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006287
6288 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6289 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006290 attr = xmlSchemaGetPropNode(node, "ref");
6291 nameAttr = xmlSchemaGetPropNode(node, "name");
6292
6293 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006294 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006295 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006296 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006297 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006298 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6299 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 "One of the attributes 'ref' or 'name' must be present");
6301 return (NULL);
6302 }
6303 if ((topLevel) || (attr == NULL)) {
6304 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006305 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6306 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006307 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006308 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006309 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006310 isRef = 1;
6311
Daniel Veillardc0826a72004-08-10 14:17:33 +00006312 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006313 char buf[50];
6314 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006315
6316 /*
6317 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006318 */
6319 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6320 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6321 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006322 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006323 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006324 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006325 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006326 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006327 if (ret == NULL) {
6328 if (repName != NULL)
6329 xmlFree(repName);
6330 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006331 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006332 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6333 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006334 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006335 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006336 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6337 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006338 /*
6339 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6340 */
6341 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006342 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6343 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006344 "ref", "name");
6345 /*
6346 * Check for illegal attributes.
6347 */
6348 attr = node->properties;
6349 while (attr != NULL) {
6350 if (attr->ns == NULL) {
6351 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6352 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006353 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006354 * 3.2.3 : 3.2
6355 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006356 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006357 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006358 xmlSchemaPIllegalAttrErr(ctxt,
6359 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006360 (xmlSchemaTypePtr) ret, attr);
6361 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6362 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6363 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006364 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6365 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006366 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006367 xmlSchemaPIllegalAttrErr(ctxt,
6368 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6369 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006370 }
6371 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006372 xmlSchemaPIllegalAttrErr(ctxt,
6373 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6374 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006375 }
6376 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006377 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006378 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006379 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006380
Daniel Veillardc0826a72004-08-10 14:17:33 +00006381 /*
6382 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006383 */
6384 if (xmlSchemaPValAttrNode(ctxt,
6385 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006386 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6387 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006388 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006389 /*
6390 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6391 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006392 /*
6393 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6394 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 */
6396 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006397 xmlSchemaPSimpleTypeErr(ctxt,
6398 XML_SCHEMAP_NO_XMLNS,
6399 NULL, (xmlNodePtr) nameAttr,
6400 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6401 "The value of type 'xs:NCName' must not match 'xmlns'",
6402 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006403 if (repName != NULL)
6404 xmlFree(repName);
6405 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006406 }
6407 /*
6408 * Evaluate the target namespace
6409 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006410 if (topLevel) {
6411 ns = schema->targetNamespace;
6412 } else {
6413 attr = xmlSchemaGetPropNode(node, "form");
6414 if (attr != NULL) {
6415 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6416 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6417 ns = schema->targetNamespace;
6418 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006419 xmlSchemaPSimpleTypeErr(ctxt,
6420 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6421 NULL, (xmlNodePtr) attr,
6422 NULL, "(qualified | unqualified)",
6423 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006424 }
6425 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006426 ns = schema->targetNamespace;
6427 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006428 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006429 if (ret == NULL) {
6430 if (repName != NULL)
6431 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006432 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006433 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006434 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006435 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006436 if (topLevel)
6437 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006438 /*
6439 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6440 * TODO: Move this to the component layer.
6441 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006442 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006443 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006444 XML_SCHEMAP_NO_XSI,
6445 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006446 "The target namespace must not match '%s'",
6447 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006448 }
6449 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006450 * Check for illegal attributes.
6451 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006452 attr = node->properties;
6453 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006454 if (attr->ns == NULL) {
6455 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6456 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6457 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6459 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006460 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006461 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6462 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006463 xmlSchemaPIllegalAttrErr(ctxt,
6464 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6465 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006466 }
6467 }
6468 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006469 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6470 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 }
6472 attr = attr->next;
6473 }
6474 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006475 node, "type", &ret->typeNs, &ret->typeName);
6476 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006477 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6478 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006479 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006480 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006481 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006482 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6483 if (ret->defValue != NULL)
6484 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006485 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006486 * Attribute "default".
6487 */
6488 attr = xmlSchemaGetPropNode(node, "default");
6489 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006490 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006491 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006492 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006493 */
6494 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6495 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6496 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6497 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006498 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6499 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006500 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006501 /*
6502 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006503 */
6504 attr = xmlSchemaGetPropNode(node, "use");
6505 if (attr != NULL) {
6506 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6507 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6508 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6509 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6510 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6511 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6512 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6513 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006514 xmlSchemaPSimpleTypeErr(ctxt,
6515 XML_SCHEMAP_INVALID_ATTR_USE,
6516 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6517 NULL, "(optional | prohibited | required)",
6518 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006519 } else
6520 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006521 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006522 * 3.2.3 : 2
6523 * If default and use are both present, use must have
6524 * the actual value optional.
6525 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006526 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6527 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006528 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006529 xmlSchemaPSimpleTypeErr(ctxt,
6530 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6531 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6532 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006533 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006534 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006535 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 /*
6538 * And now for the children...
6539 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006540 child = node->children;
6541 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006542 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6543 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006544 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006545 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 * 3.2.3 : 3.2
6550 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006551 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006552 */
6553 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6554 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6555 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006556 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6558 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006559 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006560 }
6561 } else {
6562 if (IS_SCHEMA(child, "simpleType")) {
6563 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006564 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006565 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006566 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567 */
6568 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6569 &repName, (xmlSchemaTypePtr) ret, node, child,
6570 "The attribute 'type' and the <simpleType> child "
6571 "are mutually exclusive", NULL);
6572 } else
6573 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6574 child = child->next;
6575 }
6576 if (child != NULL)
6577 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6578 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6579 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006580 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006581 /*
6582 * Cleanup.
6583 */
6584 if (repName != NULL)
6585 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006586 return (ret);
6587}
6588
6589/**
6590 * xmlSchemaParseAttributeGroup:
6591 * @ctxt: a schema validation context
6592 * @schema: the schema being built
6593 * @node: a subtree containing XML Schema informations
6594 *
6595 * parse a XML schema Attribute Group declaration
6596 * *WARNING* this interface is highly subject to change
6597 *
6598 * Returns the attribute group or NULL in case of error.
6599 */
6600static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006601xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006602 xmlSchemaPtr schema, xmlNodePtr node,
6603 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006604{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006605 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006606 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006607 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006608 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006609 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006610
6611 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6612 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006613
6614 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006615 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006616 if ((topLevel) || (attr == NULL)) {
6617 /*
6618 * Parse as an attribute group definition.
6619 * Note that those are allowed at top level only.
6620 */
6621 if (nameAttr == NULL) {
6622 xmlSchemaPMissingAttrErr(ctxt,
6623 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006624 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006625 return (NULL);
6626 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006627 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006628 * (xmlNodePtr) nameAttr);
6629 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006630 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006631 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006632 */
6633 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006634 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006635 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6636 return (NULL);
6637 }
6638 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6639 if (ret == NULL)
6640 return (NULL);
6641 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6642 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6643 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006644 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006645 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006646 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006647 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006648
6649 /*
6650 * Parse as an attribute group definition reference.
6651 */
6652 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006653 xmlSchemaPMissingAttrErr(ctxt,
6654 XML_SCHEMAP_S4S_ATTR_MISSING,
6655 NULL, node, "ref", NULL);
6656 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006657 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006658 NULL, NULL, attr, &refNs,&ref);
6659
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006660 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006661 name = (const xmlChar *) buf;
6662 if (name == NULL) {
6663 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6664 "attribute group definition reference", node);
6665 return (NULL);
6666 }
6667 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6668 if (ret == NULL)
6669 return (NULL);
6670 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6671 ret->ref = ref;
6672 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006673 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006674 xmlSchemaCheckReference(ctxt, schema, node,
6675 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006676 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006677 /*
6678 * Check for illegal attributes.
6679 */
6680 attr = node->properties;
6681 while (attr != NULL) {
6682 if (attr->ns == NULL) {
6683 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6684 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006685 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006686 {
6687 xmlSchemaPIllegalAttrErr(ctxt,
6688 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6689 NULL, NULL, attr);
6690 }
6691 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6692 xmlSchemaPIllegalAttrErr(ctxt,
6693 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6694 NULL, NULL, attr);
6695 }
6696 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006697 }
6698 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006699 /*
6700 * And now for the children...
6701 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006702 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006703 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006704 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006705 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006706 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006708 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006709 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006710 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006711 if (IS_SCHEMA(child, "anyAttribute")) {
6712 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6713 child = child->next;
6714 }
6715 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006716 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006717 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006718 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6719 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006720 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006721 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006722 ctxt->container = oldcontainer;
6723 return (ret);
6724}
6725
6726/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006727 * xmlSchemaPValAttrFormDefault:
6728 * @value: the value
6729 * @flags: the flags to be modified
6730 * @flagQualified: the specific flag for "qualified"
6731 *
6732 * Returns 0 if the value is valid, 1 otherwise.
6733 */
6734static int
6735xmlSchemaPValAttrFormDefault(const xmlChar *value,
6736 int *flags,
6737 int flagQualified)
6738{
6739 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6740 if ((*flags & flagQualified) == 0)
6741 *flags |= flagQualified;
6742 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006743 return (1);
6744
William M. Brack2f2a6632004-08-20 23:09:47 +00006745 return (0);
6746}
6747
6748/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006749 * xmlSchemaPValAttrBlockFinal:
6750 * @value: the value
6751 * @flags: the flags to be modified
6752 * @flagAll: the specific flag for "#all"
6753 * @flagExtension: the specific flag for "extension"
6754 * @flagRestriction: the specific flag for "restriction"
6755 * @flagSubstitution: the specific flag for "substitution"
6756 * @flagList: the specific flag for "list"
6757 * @flagUnion: the specific flag for "union"
6758 *
6759 * Validates the value of the attribute "final" and "block". The value
6760 * is converted into the specified flag values and returned in @flags.
6761 *
6762 * Returns 0 if the value is valid, 1 otherwise.
6763 */
6764
6765static int
6766xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006767 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006768 int flagAll,
6769 int flagExtension,
6770 int flagRestriction,
6771 int flagSubstitution,
6772 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006773 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006774{
6775 int ret = 0;
6776
6777 /*
6778 * TODO: This does not check for dublicate entries.
6779 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006780 if ((flags == NULL) || (value == NULL))
6781 return (-1);
6782 if (value[0] == 0)
6783 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006784 if (xmlStrEqual(value, BAD_CAST "#all")) {
6785 if (flagAll != -1)
6786 *flags |= flagAll;
6787 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006788 if (flagExtension != -1)
6789 *flags |= flagExtension;
6790 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006791 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006792 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006793 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006794 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006795 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006796 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006797 *flags |= flagUnion;
6798 }
6799 } else {
6800 const xmlChar *end, *cur = value;
6801 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802
Daniel Veillardc0826a72004-08-10 14:17:33 +00006803 do {
6804 while (IS_BLANK_CH(*cur))
6805 cur++;
6806 end = cur;
6807 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6808 end++;
6809 if (end == cur)
6810 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006811 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006812 if (xmlStrEqual(item, BAD_CAST "extension")) {
6813 if (flagExtension != -1) {
6814 if ((*flags & flagExtension) == 0)
6815 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006816 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006817 ret = 1;
6818 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6819 if (flagRestriction != -1) {
6820 if ((*flags & flagRestriction) == 0)
6821 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006822 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006823 ret = 1;
6824 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6825 if (flagSubstitution != -1) {
6826 if ((*flags & flagSubstitution) == 0)
6827 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006828 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006829 ret = 1;
6830 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6831 if (flagList != -1) {
6832 if ((*flags & flagList) == 0)
6833 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006834 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006835 ret = 1;
6836 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6837 if (flagUnion != -1) {
6838 if ((*flags & flagUnion) == 0)
6839 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006840 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006841 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006842 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006843 ret = 1;
6844 if (item != NULL)
6845 xmlFree(item);
6846 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006847 } while ((ret == 0) && (*cur != 0));
6848 }
6849
Daniel Veillardc0826a72004-08-10 14:17:33 +00006850 return (ret);
6851}
6852
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006853static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006854xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006855 xmlSchemaIDCPtr idc,
6856 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006857 xmlAttrPtr attr,
6858 int isField)
6859{
6860 xmlNodePtr node;
6861
6862 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006863 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006864 * Schema Component Constraint: Selector Value OK
6865 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006866 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006867 * in [XPath].
6868 */
6869 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006870 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006871 XML_SCHEMAP_INTERNAL,
6872 "Internal error: xmlSchemaCheckCSelectorXPath, "
6873 "the selector is not specified.\n", NULL, NULL);
6874 return (-1);
6875 }
6876 if (attr == NULL)
6877 node = idc->node;
6878 else
6879 node = (xmlNodePtr) attr;
6880 if (selector->xpath == NULL) {
6881 xmlSchemaPCustomErr(ctxt,
6882 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006883 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6884 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006885 "The XPath expression of the selector is not valid", NULL);
6886 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6887 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006888 const xmlChar **nsArray = NULL;
6889 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006890 /*
6891 * Compile the XPath expression.
6892 */
6893 /*
6894 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006895 * TODO: Call xmlPatterncompile with different options for selector/
6896 * field.
6897 */
6898 nsList = xmlGetNsList(attr->doc, attr->parent);
6899 /*
6900 * Build an array of prefixes and namespaces.
6901 */
6902 if (nsList != NULL) {
6903 int i, count = 0;
6904 xmlNsPtr ns;
6905
6906 for (i = 0; nsList[i] != NULL; i++)
6907 count++;
6908
6909 nsArray = (const xmlChar **) xmlMalloc(
6910 (count * 2 + 1) * sizeof(const xmlChar *));
6911 if (nsArray == NULL) {
6912 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6913 NULL);
6914 return (-1);
6915 }
6916 for (i = 0; i < count; i++) {
6917 ns = nsList[i];
6918 nsArray[2 * i] = nsList[i]->href;
6919 nsArray[2 * i + 1] = nsList[i]->prefix;
6920 }
6921 nsArray[count * 2] = NULL;
6922 xmlFree(nsList);
6923 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006924 /*
6925 * TODO: Differentiate between "selector" and "field".
6926 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006927 if (isField)
6928 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006929 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006930 else
6931 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006932 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006933 if (nsArray != NULL)
6934 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006935
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006936 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006937 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006938 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006939 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6940 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006941 "The XPath expression '%s' could not be "
6942 "compiled", selector->xpath);
6943 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006944 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006945 }
6946 return (0);
6947}
6948
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006949#define ADD_ANNOTATION(annot) \
6950 xmlSchemaAnnotPtr cur = item->annot; \
6951 if (item->annot == NULL) { \
6952 item->annot = annot; \
6953 return (annot); \
6954 } \
6955 cur = item->annot; \
6956 if (cur->next != NULL) { \
6957 cur = cur->next; \
6958 } \
6959 cur->next = annot;
6960
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006961/**
6962 * xmlSchemaAssignAnnotation:
6963 * @item: the schema component
6964 * @annot: the annotation
6965 *
6966 * Adds the annotation to the given schema component.
6967 *
6968 * Returns the given annotaion.
6969 */
6970static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006971xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6972 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006973{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006974 if ((annItem == NULL) || (annot == NULL))
6975 return (NULL);
6976 switch (annItem->type) {
6977 case XML_SCHEMA_TYPE_ELEMENT: {
6978 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6979 ADD_ANNOTATION(annot)
6980 }
6981 break;
6982 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6983 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6984 ADD_ANNOTATION(annot)
6985 }
6986 break;
6987 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6988 case XML_SCHEMA_TYPE_ANY: {
6989 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6990 ADD_ANNOTATION(annot)
6991 }
6992 break;
6993 case XML_SCHEMA_TYPE_PARTICLE:
6994 case XML_SCHEMA_TYPE_IDC_KEY:
6995 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006996 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006997 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6998 ADD_ANNOTATION(annot)
6999 }
7000 break;
7001 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7002 xmlSchemaAttributeGroupPtr item =
7003 (xmlSchemaAttributeGroupPtr) annItem;
7004 ADD_ANNOTATION(annot)
7005 }
7006 break;
7007 case XML_SCHEMA_TYPE_NOTATION: {
7008 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7009 ADD_ANNOTATION(annot)
7010 }
7011 break;
7012 case XML_SCHEMA_FACET_MININCLUSIVE:
7013 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7014 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7015 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7016 case XML_SCHEMA_FACET_TOTALDIGITS:
7017 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7018 case XML_SCHEMA_FACET_PATTERN:
7019 case XML_SCHEMA_FACET_ENUMERATION:
7020 case XML_SCHEMA_FACET_WHITESPACE:
7021 case XML_SCHEMA_FACET_LENGTH:
7022 case XML_SCHEMA_FACET_MAXLENGTH:
7023 case XML_SCHEMA_FACET_MINLENGTH: {
7024 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7025 ADD_ANNOTATION(annot)
7026 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007027 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007028 case XML_SCHEMA_TYPE_SIMPLE:
7029 case XML_SCHEMA_TYPE_COMPLEX: {
7030 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7031 ADD_ANNOTATION(annot)
7032 }
7033 break;
7034 case XML_SCHEMA_TYPE_GROUP: {
7035 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7036 ADD_ANNOTATION(annot)
7037 }
7038 break;
7039 case XML_SCHEMA_TYPE_SEQUENCE:
7040 case XML_SCHEMA_TYPE_CHOICE:
7041 case XML_SCHEMA_TYPE_ALL: {
7042 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7043 ADD_ANNOTATION(annot)
7044 }
7045 break;
7046 default:
7047 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007048 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007049 NULL, NULL, NULL,
7050 "Internal error: xmlSchemaAddAnnotation, "
7051 "The item is not a annotated schema component", NULL);
7052 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007053 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007054 return (annot);
7055}
7056
7057/**
7058 * xmlSchemaParseIDCSelectorAndField:
7059 * @ctxt: a schema validation context
7060 * @schema: the schema being built
7061 * @node: a subtree containing XML Schema informations
7062 *
7063 * Parses a XML Schema identity-contraint definition's
7064 * <selector> and <field> elements.
7065 *
7066 * Returns the parsed identity-constraint definition.
7067 */
7068static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007069xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007070 xmlSchemaPtr schema,
7071 xmlSchemaIDCPtr idc,
7072 xmlNodePtr node,
7073 int isField)
7074{
7075 xmlSchemaIDCSelectPtr item;
7076 xmlNodePtr child = NULL;
7077 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007078
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007079 /*
7080 * Check for illegal attributes.
7081 */
7082 attr = node->properties;
7083 while (attr != NULL) {
7084 if (attr->ns == NULL) {
7085 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7086 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007087 xmlSchemaPIllegalAttrErr(ctxt,
7088 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7089 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007090 }
7091 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007092 xmlSchemaPIllegalAttrErr(ctxt,
7093 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7094 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007095 }
7096 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007097 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007098 /*
7099 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007100 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007101 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7102 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007103 xmlSchemaPErrMemory(ctxt,
7104 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007105 NULL);
7106 return (NULL);
7107 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007108 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007109 /*
7110 * Attribute "xpath" (mandatory).
7111 */
7112 attr = xmlSchemaGetPropNode(node, "xpath");
7113 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007114 xmlSchemaPMissingAttrErr(ctxt,
7115 XML_SCHEMAP_S4S_ATTR_MISSING,
7116 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007117 "name", NULL);
7118 } else {
7119 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7120 /*
7121 * URGENT TODO: "field"s have an other syntax than "selector"s.
7122 */
7123
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007124 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7125 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007126 xmlSchemaPErr(ctxt,
7127 (xmlNodePtr) attr,
7128 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007129 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007130 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007131 NULL, NULL);
7132 }
7133
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007134 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007135 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007136 /*
7137 * And now for the children...
7138 */
7139 child = node->children;
7140 if (IS_SCHEMA(child, "annotation")) {
7141 /*
7142 * Add the annotation to the parent IDC.
7143 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007144 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007145 xmlSchemaParseAnnotation(ctxt, schema, child));
7146 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007147 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007148 if (child != NULL) {
7149 xmlSchemaPContentErr(ctxt,
7150 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007151 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007152 NULL, "(annotation?)");
7153 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007154
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007155 return (item);
7156}
7157
7158/**
7159 * xmlSchemaParseIDC:
7160 * @ctxt: a schema validation context
7161 * @schema: the schema being built
7162 * @node: a subtree containing XML Schema informations
7163 *
7164 * Parses a XML Schema identity-contraint definition.
7165 *
7166 * Returns the parsed identity-constraint definition.
7167 */
7168static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007169xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007170 xmlSchemaPtr schema,
7171 xmlNodePtr node,
7172 xmlSchemaTypeType idcCategory,
7173 const xmlChar *targetNamespace)
7174{
7175 xmlSchemaIDCPtr item = NULL;
7176 xmlNodePtr child = NULL;
7177 xmlAttrPtr attr;
7178 const xmlChar *name = NULL;
7179 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7180 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007181
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007182 /*
7183 * Check for illegal attributes.
7184 */
7185 attr = node->properties;
7186 while (attr != NULL) {
7187 if (attr->ns == NULL) {
7188 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7189 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7190 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7191 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007192 xmlSchemaPIllegalAttrErr(ctxt,
7193 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7194 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007195 }
7196 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007197 xmlSchemaPIllegalAttrErr(ctxt,
7198 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7199 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007200 }
7201 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007202 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007203 /*
7204 * Attribute "name" (mandatory).
7205 */
7206 attr = xmlSchemaGetPropNode(node, "name");
7207 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007208 xmlSchemaPMissingAttrErr(ctxt,
7209 XML_SCHEMAP_S4S_ATTR_MISSING,
7210 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007211 "name", NULL);
7212 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007213 } else if (xmlSchemaPValAttrNode(ctxt,
7214 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007215 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7216 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007217 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007218 /*
7219 * Create the component.
7220 */
7221 if (schema->idcDef == NULL)
7222 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007223 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007224 return (NULL);
7225
7226 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7227 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007228 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007229 "allocating an identity-constraint definition", NULL);
7230 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007231 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007232 /*
7233 * Add the IDC to the list of IDCs on the schema component.
7234 */
7235 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007236 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007237 xmlSchemaPCustomErrExt(ctxt,
7238 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007239 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007240 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007241 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007242 name, targetNamespace, NULL);
7243 xmlFree(item);
7244 return (NULL);
7245 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007246 memset(item, 0, sizeof(xmlSchemaIDC));
7247 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007248 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007249 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007250 if (ctxt->assemble != NULL)
7251 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007252 /*
7253 * The target namespace of the parent element declaration.
7254 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007255 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007256 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7257 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007258 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7259 /*
7260 * Attribute "refer" (mandatory).
7261 */
7262 attr = xmlSchemaGetPropNode(node, "refer");
7263 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007264 xmlSchemaPMissingAttrErr(ctxt,
7265 XML_SCHEMAP_S4S_ATTR_MISSING,
7266 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007267 "refer", NULL);
7268 } else {
7269 /*
7270 * Create a reference item.
7271 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007272 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007273 NULL, NULL);
7274 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007275 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007276 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007277 NULL, NULL, attr,
7278 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007279 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007280 xmlSchemaCheckReference(ctxt, schema, node,
7281 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007282 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007283 }
7284 }
7285 /*
7286 * And now for the children...
7287 */
7288 child = node->children;
7289 if (IS_SCHEMA(child, "annotation")) {
7290 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7291 child = child->next;
7292 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007293 if (child == NULL) {
7294 xmlSchemaPContentErr(ctxt,
7295 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007296 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007297 "A child element is missing",
7298 "(annotation?, (selector, field+))");
7299 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007300 /*
7301 * Child element <selector>.
7302 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007303 if (IS_SCHEMA(child, "selector")) {
7304 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007305 item, child, 0);
7306 child = child->next;
7307 /*
7308 * Child elements <field>.
7309 */
7310 if (IS_SCHEMA(child, "field")) {
7311 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007312 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007313 item, child, 1);
7314 if (field != NULL) {
7315 field->index = item->nbFields;
7316 item->nbFields++;
7317 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007318 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007319 else
7320 item->fields = field;
7321 lastField = field;
7322 }
7323 child = child->next;
7324 } while (IS_SCHEMA(child, "field"));
7325 } else {
7326 xmlSchemaPContentErr(ctxt,
7327 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007328 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007329 NULL, "(annotation?, (selector, field+))");
7330 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007331 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007332 if (child != NULL) {
7333 xmlSchemaPContentErr(ctxt,
7334 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007335 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007336 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007337 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007338
7339 return (item);
7340}
7341
Daniel Veillardc0826a72004-08-10 14:17:33 +00007342/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007343 * xmlSchemaParseElement:
7344 * @ctxt: a schema validation context
7345 * @schema: the schema being built
7346 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007347 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007348 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007349 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007350 * *WARNING* this interface is highly subject to change
7351 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007352 * Returns the element declaration or a particle; NULL in case
7353 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007354 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007355static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007356xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007357 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007358{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007359 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007360 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007361 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007362 xmlNodePtr child = NULL;
7363 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007364 int min, max, isRef = 0;
7365 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007366
7367 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7368 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007369
Daniel Veillard4255d502002-04-16 15:50:10 +00007370 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007371 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007372 /*
7373 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007374 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007375 * robust.
7376 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007377 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007378 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007379 if ((topLevel) || (attr == NULL)) {
7380 if (nameAttr == NULL) {
7381 xmlSchemaPMissingAttrErr(ctxt,
7382 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007383 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007384 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007385 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007386 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007387 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007388
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007389 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007390 child = node->children;
7391 if (IS_SCHEMA(child, "annotation")) {
7392 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7393 child = child->next;
7394 }
7395 /*
7396 * Skip particle part if a global declaration.
7397 */
7398 if (topLevel)
7399 goto declaration_part;
7400 /*
7401 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007402 */
7403 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7404 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7405 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007406 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7407 if (particle == NULL)
7408 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007409
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007410 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7411
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007412 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007413 const xmlChar *refNs = NULL, *ref = NULL;
7414 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007415 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007416 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007417 */
7418 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007419 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007420 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007421 /*
7422 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007423 */
7424 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007425 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007426 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007427 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007428 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007429 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007430 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007431 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007432 attr = node->properties;
7433 while (attr != NULL) {
7434 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007435 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7436 xmlStrEqual(attr->name, BAD_CAST "name") ||
7437 xmlStrEqual(attr->name, BAD_CAST "id") ||
7438 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7439 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7440 {
7441 attr = attr->next;
7442 continue;
7443 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007444 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007445 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007446 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007447 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007448 "Only the attributes 'minOccurs', 'maxOccurs' and "
7449 "'id' are allowed in addition to 'ref'");
7450 break;
7451 }
7452 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7453 xmlSchemaPIllegalAttrErr(ctxt,
7454 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007455 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007456 }
7457 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007458 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007459 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007460 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007461 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007462 if (child != NULL) {
7463 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 NULL, NULL, node, child, NULL, "(annotation?)");
7465 }
7466 if ((min == 0) && (max == 0))
7467 goto return_null;
7468 /*
7469 * Create the reference item.
7470 */
7471 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7472 ref, refNs);
7473 if (refer == NULL)
7474 goto return_null;
7475 particle->children = (xmlSchemaTreeItemPtr) refer;
7476 particle->annot = annot;
7477 /*
7478 * Add to assembled items; the reference need to be resolved.
7479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007480 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007481 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7482
7483 return ((xmlSchemaBasicItemPtr) particle);
7484 }
7485 /*
7486 * The declaration part ===============================================
7487 */
7488declaration_part:
7489 {
7490 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7491 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7492
7493 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007494 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007495 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007496 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007497 * Evaluate the target namespace.
7498 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007499 if (topLevel) {
7500 ns = schema->targetNamespace;
7501 } else {
7502 attr = xmlSchemaGetPropNode(node, "form");
7503 if (attr != NULL) {
7504 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7505 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007506 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007507 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007508 xmlSchemaPSimpleTypeErr(ctxt,
7509 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7510 NULL, (xmlNodePtr) attr,
7511 NULL, "(qualified | unqualified)",
7512 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007513 }
7514 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007515 ns = schema->targetNamespace;
7516 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007517 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007518 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007519 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007520 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007521 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7522 decl->node = node;
7523 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007524 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007525 * Check for illegal attributes.
7526 */
William M. Bracke7091952004-05-11 15:09:58 +00007527 attr = node->properties;
7528 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007529 if (attr->ns == NULL) {
7530 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7531 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007532 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007533 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007534 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007536 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7537 {
7538 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007539 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007540 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007541 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007542 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007543 xmlSchemaPIllegalAttrErr(ctxt,
7544 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7545 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007546 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007547 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7548 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007549 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7550
7551 xmlSchemaPIllegalAttrErr(ctxt,
7552 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007553 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007554 }
7555 }
7556 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007557
Daniel Veillardc0826a72004-08-10 14:17:33 +00007558 xmlSchemaPIllegalAttrErr(ctxt,
7559 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007560 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007561 }
7562 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007563 }
William M. Bracke7091952004-05-11 15:09:58 +00007564 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007565 * Extract/validate attributes.
7566 */
7567 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007568 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007569 * Process top attributes of global element declarations here.
7570 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007571 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7572 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007573 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7574 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7575 &(decl->substGroupNs), &(decl->substGroup));
7576 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007577 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007578 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007579 /*
7580 * Attribute "final".
7581 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007582 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007583 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007584 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7585 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7586 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7587 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007588 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007589 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7590 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007591 -1,
7592 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7593 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007594 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007595 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007596 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7597 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007598 attrValue, NULL, NULL, NULL);
7599 }
7600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007601 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007602 /*
7603 * Attribute "block".
7604 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007605 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007606 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007607 /*
7608 * Apply default "block" values.
7609 */
7610 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7611 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7612 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7613 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7614 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7615 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007616 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007617 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7618 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007619 -1,
7620 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007621 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007622 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7623 xmlSchemaPSimpleTypeErr(ctxt,
7624 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007625 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007626 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007627 "restriction | substitution))", attrValue,
7628 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007629 }
7630 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007631 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007632 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007633 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007634
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007635 attr = xmlSchemaGetPropNode(node, "type");
7636 if (attr != NULL) {
7637 xmlSchemaPValAttrNodeQName(ctxt, schema,
7638 NULL, (xmlSchemaTypePtr) decl, attr,
7639 &(decl->namedTypeNs), &(decl->namedType));
7640 xmlSchemaCheckReference(ctxt, schema, node,
7641 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7642 }
7643 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7644 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007645 if (attr != NULL) {
7646 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007647 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007648 /*
7649 * 3.3.3 : 1
7650 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007651 */
7652 xmlSchemaPMutualExclAttrErr(ctxt,
7653 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007654 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007655 "default", "fixed");
7656 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007657 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7658 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007659 }
William M. Bracke7091952004-05-11 15:09:58 +00007660 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007661 /*
7662 * And now for the children...
7663 */
7664 oldcontainer = ctxt->container;
7665 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007666 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007667 /*
7668 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007669 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007670 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007671 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007672 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007673 xmlSchemaPContentErr(ctxt,
7674 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007675 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007676 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007677 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007678 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007679 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007680 child = child->next;
7681 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007682 /*
7683 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007684 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007685 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007686 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007687 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 xmlSchemaPContentErr(ctxt,
7689 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007690 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007691 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007692 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007693 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007694 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007695 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007696 }
William M. Bracke7091952004-05-11 15:09:58 +00007697 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007698 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007699 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007700 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007701 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007702 } else if (IS_SCHEMA(child, "key")) {
7703 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007704 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007705 } else if (IS_SCHEMA(child, "keyref")) {
7706 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007707 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007708 }
7709 if (lastIDC != NULL)
7710 lastIDC->next = curIDC;
7711 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007712 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007713 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007714 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007715 }
7716 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007717 xmlSchemaPContentErr(ctxt,
7718 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007719 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007720 NULL, "(annotation?, ((simpleType | complexType)?, "
7721 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007722 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007723 ctxt->container = oldcontainer;
7724 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007725 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007726 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007727 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007728 * different layer.
7729 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007730 FREE_AND_NULL(des)
7731 if (topLevel)
7732 return ((xmlSchemaBasicItemPtr) decl);
7733 else {
7734 particle->children = (xmlSchemaTreeItemPtr) decl;
7735 return ((xmlSchemaBasicItemPtr) particle);
7736 }
7737
7738return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007739 FREE_AND_NULL(des);
7740 if (annot != NULL) {
7741 if (particle != NULL)
7742 particle->annot = NULL;
7743 if (decl != NULL)
7744 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007745 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007746 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007747 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007748}
7749
7750/**
7751 * xmlSchemaParseUnion:
7752 * @ctxt: a schema validation context
7753 * @schema: the schema being built
7754 * @node: a subtree containing XML Schema informations
7755 *
7756 * parse a XML schema Union definition
7757 * *WARNING* this interface is highly subject to change
7758 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007759 * Returns -1 in case of internal error, 0 in case of success and a positive
7760 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007761 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007762static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007763xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007764 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007766 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007767 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007768 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007769 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007770
7771 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007772 return (-1);
7773 /* Not a component, don't create it. */
7774 type = ctxt->ctxtType;
7775 /*
7776 * Mark the simple type as being of variety "union".
7777 */
7778 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007779 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007780 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7781 * then the ·simple ur-type definition·."
7782 */
7783 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007784 /*
7785 * Check for illegal attributes.
7786 */
7787 attr = node->properties;
7788 while (attr != NULL) {
7789 if (attr->ns == NULL) {
7790 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7791 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007792 xmlSchemaPIllegalAttrErr(ctxt,
7793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7794 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007795 }
7796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007797 xmlSchemaPIllegalAttrErr(ctxt,
7798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7799 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007800 }
7801 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007802 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007803 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007804 /*
7805 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007806 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007807 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007808 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007809 if (attr != NULL) {
7810 const xmlChar *end;
7811 xmlChar *tmp;
7812 const xmlChar *localName, *nsName;
7813 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7814 xmlSchemaQNameRefPtr ref;
7815
7816 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007817 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007818 do {
7819 while (IS_BLANK_CH(*cur))
7820 cur++;
7821 end = cur;
7822 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7823 end++;
7824 if (end == cur)
7825 break;
7826 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007827 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7828 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007829 /*
7830 * Create the member type link.
7831 */
7832 link = (xmlSchemaTypeLinkPtr)
7833 xmlMalloc(sizeof(xmlSchemaTypeLink));
7834 if (link == NULL) {
7835 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7836 "allocating a type link", NULL);
7837 return (-1);
7838 }
7839 link->type = NULL;
7840 link->next = NULL;
7841 if (lastLink == NULL)
7842 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007843 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007844 lastLink->next = link;
7845 lastLink = link;
7846 /*
7847 * Create a reference item.
7848 */
7849 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7850 localName, nsName);
7851 if (ref == NULL) {
7852 FREE_AND_NULL(tmp)
7853 return (-1);
7854 }
7855 /*
7856 * Assign the reference to the link, it will be resolved
7857 * later during fixup of the union simple type.
7858 */
7859 link->type = (xmlSchemaTypePtr) ref;
7860 }
7861 FREE_AND_NULL(tmp)
7862 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007863 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007864
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007865 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007866 /*
7867 * And now for the children...
7868 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007869 child = node->children;
7870 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007871 /*
7872 * Add the annotation to the simple type ancestor.
7873 */
7874 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7875 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007876 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007877 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007878 if (IS_SCHEMA(child, "simpleType")) {
7879 xmlSchemaTypePtr subtype, last = NULL;
7880
7881 /*
7882 * Anchor the member types in the "subtypes" field of the
7883 * simple type.
7884 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007885 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007886 subtype = (xmlSchemaTypePtr)
7887 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7888 if (subtype != NULL) {
7889 if (last == NULL) {
7890 type->subtypes = subtype;
7891 last = subtype;
7892 } else {
7893 last->next = subtype;
7894 last = subtype;
7895 }
7896 last->next = NULL;
7897 }
7898 child = child->next;
7899 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007900 }
7901 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007902 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007903 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007904 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007905 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007906 if ((attr == NULL) && (type->subtypes == NULL)) {
7907 /*
7908 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007909 * Either the memberTypes [attribute] of the <union> element must
7910 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007911 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007912 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007913 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7914 NULL, NULL, node,
7915 "Either the attribute 'memberTypes' or "
7916 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007917 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007918 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007919}
7920
7921/**
7922 * xmlSchemaParseList:
7923 * @ctxt: a schema validation context
7924 * @schema: the schema being built
7925 * @node: a subtree containing XML Schema informations
7926 *
7927 * parse a XML schema List definition
7928 * *WARNING* this interface is highly subject to change
7929 *
William M. Bracke7091952004-05-11 15:09:58 +00007930 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007931 * 1 in case of success.
7932 */
7933static xmlSchemaTypePtr
7934xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007935 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007936{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007937 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007938 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007939 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007940
7941 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7942 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007943 /* Not a component, don't create it. */
7944 type = ctxt->ctxtType;
7945 /*
7946 * Mark the type as being of variety "list".
7947 */
7948 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007949 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007950 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7951 * then the ·simple ur-type definition·."
7952 */
7953 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007954 /*
7955 * Check for illegal attributes.
7956 */
7957 attr = node->properties;
7958 while (attr != NULL) {
7959 if (attr->ns == NULL) {
7960 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7961 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007962 xmlSchemaPIllegalAttrErr(ctxt,
7963 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7964 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007965 }
7966 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007967 xmlSchemaPIllegalAttrErr(ctxt,
7968 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7969 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007970 }
7971 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007972 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007973
7974 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7975
William M. Brack2f2a6632004-08-20 23:09:47 +00007976 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007977 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7978 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007979 */
7980 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007981 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007982 /*
7983 * And now for the children...
7984 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007985 child = node->children;
7986 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7988 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007989 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007990 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007991 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007992 /*
7993 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007994 * Either the itemType [attribute] or the <simpleType> [child] of
7995 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007996 */
7997 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007998 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00007999 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008000 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008001 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008002 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008003 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008004 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008005 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008006 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008007 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008008 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008009 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008010 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008011 "Either the attribute 'itemType' or the <simpleType> child "
8012 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008013 }
8014 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008015 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008016 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008017 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008018 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008019 if ((type->ref == NULL) &&
8020 (type->subtypes == NULL) &&
8021 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008022 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008023 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008024 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008025 "Either the attribute 'itemType' or the <simpleType> child "
8026 "must be present", NULL);
8027 }
8028 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008029}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008030
Daniel Veillard4255d502002-04-16 15:50:10 +00008031/**
8032 * xmlSchemaParseSimpleType:
8033 * @ctxt: a schema validation context
8034 * @schema: the schema being built
8035 * @node: a subtree containing XML Schema informations
8036 *
8037 * parse a XML schema Simple Type definition
8038 * *WARNING* this interface is highly subject to change
8039 *
William M. Bracke7091952004-05-11 15:09:58 +00008040 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008041 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008042 */
8043static xmlSchemaTypePtr
8044xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008045 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008046{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008047 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008048 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008049 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008050 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008051
8052 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8053 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008054
Daniel Veillardc0826a72004-08-10 14:17:33 +00008055 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008056 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008057 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008058 xmlSchemaPMissingAttrErr(ctxt,
8059 XML_SCHEMAP_S4S_ATTR_MISSING,
8060 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008061 "name", NULL);
8062 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008063 } else {
8064 if (xmlSchemaPValAttrNode(ctxt,
8065 NULL, NULL, attr,
8066 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8067 return (NULL);
8068 /*
8069 * Skip built-in types.
8070 */
8071 if (ctxt->isS4S) {
8072 xmlSchemaTypePtr biType;
8073
8074 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8075 if (biType != NULL)
8076 return (biType);
8077 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008078 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008079 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008080
Daniel Veillardc0826a72004-08-10 14:17:33 +00008081 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008082 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008083
Daniel Veillard01fa6152004-06-29 17:04:39 +00008084 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008085 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008086 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008087 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008088 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008089 if (type == NULL)
8090 return (NULL);
8091 type->node = node;
8092 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008093 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008094 /*
8095 * Check for illegal attributes.
8096 */
8097 attr = node->properties;
8098 while (attr != NULL) {
8099 if (attr->ns == NULL) {
8100 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008101 xmlSchemaPIllegalAttrErr(ctxt,
8102 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8103 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008104 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008105 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008106 xmlSchemaPIllegalAttrErr(ctxt,
8107 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8108 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008109 }
8110 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008111 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008112 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008113 /*
8114 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008115 *
8116 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008117 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008118 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008119 if (type == NULL)
8120 return (NULL);
8121 type->node = node;
8122 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008123 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008124 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8125 /*
8126 * Check for illegal attributes.
8127 */
8128 attr = node->properties;
8129 while (attr != NULL) {
8130 if (attr->ns == NULL) {
8131 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8132 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008133 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008134 xmlSchemaPIllegalAttrErr(ctxt,
8135 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8136 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008137 }
8138 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008139 xmlSchemaPIllegalAttrErr(ctxt,
8140 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8141 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008142 }
8143 attr = attr->next;
8144 }
8145 /*
8146 * Attribute "final".
8147 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008148 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008149 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008150 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8151 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8152 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8153 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8154 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8155 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008156 } else {
8157 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008158 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8159 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008160 XML_SCHEMAS_TYPE_FINAL_LIST,
8161 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8162
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008163 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008164 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008165 type, (xmlNodePtr) attr,
8166 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008167 attrValue, NULL, NULL, NULL);
8168 }
8169 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008170 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008171 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008172 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008173 /*
8174 * And now for the children...
8175 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008176 oldCtxtType = ctxt->ctxtType;
8177 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008178 ctxt->ctxtType = type;
8179 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008180 child = node->children;
8181 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008182 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8183 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008184 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008185 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008186 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8187 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008188 "(annotation?, (restriction | list | union))");
8189 } else if (IS_SCHEMA(child, "restriction")) {
8190 xmlSchemaParseRestriction(ctxt, schema, child,
8191 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008192 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008193 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008194 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008195 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008196 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008197 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008198 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008199 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008200 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008201 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8202 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008203 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008204 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008205 ctxt->parentItem = oldParentItem;
8206 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008207
Daniel Veillard4255d502002-04-16 15:50:10 +00008208 return (type);
8209}
8210
Daniel Veillard4255d502002-04-16 15:50:10 +00008211/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008212 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008213 * @ctxt: a schema validation context
8214 * @schema: the schema being built
8215 * @node: a subtree containing XML Schema informations
8216 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008217 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008218 * *WARNING* this interface is highly subject to change
8219 *
William M. Bracke7091952004-05-11 15:09:58 +00008220 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008221 * 1 in case of success.
8222 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008223static xmlSchemaTreeItemPtr
8224xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8225 xmlSchemaPtr schema,
8226 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008227{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008228 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008229 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008230 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008231 const xmlChar *ref = NULL, *refNs = NULL;
8232 int min, max;
8233
8234 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008235 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008236
8237 attr = xmlSchemaGetPropNode(node, "ref");
8238 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008239 xmlSchemaPMissingAttrErr(ctxt,
8240 XML_SCHEMAP_S4S_ATTR_MISSING,
8241 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008242 "ref", NULL);
8243 return (NULL);
8244 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008245 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008246 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008247 }
8248 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008249 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008250 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008251 /*
8252 * Check for illegal attributes.
8253 */
8254 attr = node->properties;
8255 while (attr != NULL) {
8256 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008257 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008258 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8259 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8260 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008261 xmlSchemaPIllegalAttrErr(ctxt,
8262 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8263 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008264 }
8265 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008266 xmlSchemaPIllegalAttrErr(ctxt,
8267 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8268 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008269 }
8270 attr = attr->next;
8271 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008272 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008273 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8274 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008275 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008276 /*
8277 * Create a reference item as the term; it will be substituted for
8278 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008279 */
8280 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008281 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8282 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8283 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8284 /*
8285 * And now for the children...
8286 */
8287 child = node->children;
8288 /* TODO: Is annotation even allowed for a model group reference? */
8289 if (IS_SCHEMA(child, "annotation")) {
8290 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008291 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008292 */
8293 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8294 child = child->next;
8295 }
8296 if (child != NULL) {
8297 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008298 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008299 NULL, NULL, node, child, NULL,
8300 "(annotation?)");
8301 }
8302 /*
8303 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8304 */
8305 if ((min == 0) && (max == 0))
8306 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008307 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008308 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8309 return ((xmlSchemaTreeItemPtr) item);
8310}
8311
8312/**
8313 * xmlSchemaParseModelGroupDefinition:
8314 * @ctxt: a schema validation context
8315 * @schema: the schema being built
8316 * @node: a subtree containing XML Schema informations
8317 *
8318 * Parses a XML schema model group definition.
8319 * *WARNING* this interface is highly subject to change
8320 *
8321 * Returns -1 in case of error, 0 if the declaration is improper and
8322 * 1 in case of success.
8323 */
8324static xmlSchemaModelGroupDefPtr
8325xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8326 xmlSchemaPtr schema,
8327 xmlNodePtr node)
8328{
8329 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008330 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008331 xmlAttrPtr attr;
8332 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008333
8334 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008335 return (NULL);
8336
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008337 attr = xmlSchemaGetPropNode(node, "name");
8338 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008339 xmlSchemaPMissingAttrErr(ctxt,
8340 XML_SCHEMAP_S4S_ATTR_MISSING,
8341 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008342 "name", NULL);
8343 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008344 } else if (xmlSchemaPValAttrNode(ctxt,
8345 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008346 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8347 return (NULL);
8348 }
8349 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8350 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008351 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008352 /*
8353 * Check for illegal attributes.
8354 */
8355 attr = node->properties;
8356 while (attr != NULL) {
8357 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008358 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008359 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008360 xmlSchemaPIllegalAttrErr(ctxt,
8361 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8362 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008363 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008364 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008365 xmlSchemaPIllegalAttrErr(ctxt,
8366 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8367 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008368 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008369 attr = attr->next;
8370 }
8371 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8372 /*
8373 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008374 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008375 child = node->children;
8376 if (IS_SCHEMA(child, "annotation")) {
8377 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8378 child = child->next;
8379 }
8380 if (IS_SCHEMA(child, "all")) {
8381 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8382 XML_SCHEMA_TYPE_ALL, 0);
8383 child = child->next;
8384 } else if (IS_SCHEMA(child, "choice")) {
8385 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8386 XML_SCHEMA_TYPE_CHOICE, 0);
8387 child = child->next;
8388 } else if (IS_SCHEMA(child, "sequence")) {
8389 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8390 XML_SCHEMA_TYPE_SEQUENCE, 0);
8391 child = child->next;
8392 }
8393 if (child != NULL) {
8394 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008395 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8396 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008397 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008398 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008399
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008400 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008401}
8402
8403/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008404 * xmlSchemaCleanupDoc:
8405 * @ctxt: a schema validation context
8406 * @node: the root of the document.
8407 *
8408 * removes unwanted nodes in a schemas document tree
8409 */
8410static void
8411xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8412{
8413 xmlNodePtr delete, cur;
8414
8415 if ((ctxt == NULL) || (root == NULL)) return;
8416
8417 /*
8418 * Remove all the blank text nodes
8419 */
8420 delete = NULL;
8421 cur = root;
8422 while (cur != NULL) {
8423 if (delete != NULL) {
8424 xmlUnlinkNode(delete);
8425 xmlFreeNode(delete);
8426 delete = NULL;
8427 }
8428 if (cur->type == XML_TEXT_NODE) {
8429 if (IS_BLANK_NODE(cur)) {
8430 if (xmlNodeGetSpacePreserve(cur) != 1) {
8431 delete = cur;
8432 }
8433 }
8434 } else if ((cur->type != XML_ELEMENT_NODE) &&
8435 (cur->type != XML_CDATA_SECTION_NODE)) {
8436 delete = cur;
8437 goto skip_children;
8438 }
8439
8440 /*
8441 * Skip to next node
8442 */
8443 if (cur->children != NULL) {
8444 if ((cur->children->type != XML_ENTITY_DECL) &&
8445 (cur->children->type != XML_ENTITY_REF_NODE) &&
8446 (cur->children->type != XML_ENTITY_NODE)) {
8447 cur = cur->children;
8448 continue;
8449 }
8450 }
8451 skip_children:
8452 if (cur->next != NULL) {
8453 cur = cur->next;
8454 continue;
8455 }
8456
8457 do {
8458 cur = cur->parent;
8459 if (cur == NULL)
8460 break;
8461 if (cur == root) {
8462 cur = NULL;
8463 break;
8464 }
8465 if (cur->next != NULL) {
8466 cur = cur->next;
8467 break;
8468 }
8469 } while (cur != NULL);
8470 }
8471 if (delete != NULL) {
8472 xmlUnlinkNode(delete);
8473 xmlFreeNode(delete);
8474 delete = NULL;
8475 }
8476}
8477
William M. Brack2f2a6632004-08-20 23:09:47 +00008478
8479/**
8480 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008481 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008482 * @ctxt: a schema validation context
8483 * @schemaLocation: an URI defining where to find the imported schema
8484 *
8485 * import a XML schema
8486 * *WARNING* this interface is highly subject to change
8487 *
8488 * Returns -1 in case of error and 1 in case of success.
8489 */
8490#if 0
8491static xmlSchemaImportPtr
8492xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8493 const xmlChar *schemaLocation)
8494{
8495 xmlSchemaImportPtr import;
8496 xmlSchemaParserCtxtPtr newctxt;
8497
8498 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8499 if (newctxt == NULL) {
8500 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8501 NULL);
8502 return (NULL);
8503 }
8504 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8505 /* Keep the same dictionnary for parsing, really */
8506 xmlDictReference(ctxt->dict);
8507 newctxt->dict = ctxt->dict;
8508 newctxt->includes = 0;
8509 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8510
8511 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8512 ctxt->userData);
8513
8514 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8515 if (import == NULL) {
8516 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8517 NULL);
8518 xmlSchemaFreeParserCtxt(newctxt);
8519 return (NULL);
8520 }
8521
8522 memset(import, 0, sizeof(xmlSchemaImport));
8523 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8524 import->schema = xmlSchemaParse(newctxt);
8525
8526 if (import->schema == NULL) {
8527 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008528 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008529 "Failed to import schema from location \"%s\".\n",
8530 schemaLocation, NULL);
8531
8532 xmlSchemaFreeParserCtxt(newctxt);
8533 /* The schemaLocation is held by the dictionary.
8534 if (import->schemaLocation != NULL)
8535 xmlFree((xmlChar *)import->schemaLocation);
8536 */
8537 xmlFree(import);
8538 return NULL;
8539 }
8540
8541 xmlSchemaFreeParserCtxt(newctxt);
8542 return import;
8543}
8544#endif
8545
8546static void
8547xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8548{
8549 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8550 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8551
8552 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8553 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8554
8555 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8556 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8557 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8558 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8559 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8560 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8561 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8562 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8563
8564 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8565 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8566 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8567 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8568 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8569 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8570}
8571
8572static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008573xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008574 xmlSchemaPtr schema,
8575 xmlNodePtr node)
8576{
8577 xmlAttrPtr attr;
8578 const xmlChar *val;
8579
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008580 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8581 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008582 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008583 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8584 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008585 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008586 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008588 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008589 if (attr != NULL) {
8590 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008592 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008593 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008594 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008595 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008596 "(qualified | unqualified)", val, NULL, NULL, NULL);
8597 }
8598 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008599
8600 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008601 if (attr != NULL) {
8602 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008604 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008606 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008607 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008608 "(qualified | unqualified)", val, NULL, NULL, NULL);
8609 }
8610 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008611
8612 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008613 if (attr != NULL) {
8614 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8615 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8616 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8617 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8618 -1,
8619 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8620 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8621 xmlSchemaPSimpleTypeErr(ctxt,
8622 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008623 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008624 "(#all | List of (extension | restriction | list | union))",
8625 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008626 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008627 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008628
8629 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008630 if (attr != NULL) {
8631 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8632 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8633 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8634 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8635 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8636 xmlSchemaPSimpleTypeErr(ctxt,
8637 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008639 "(#all | List of (extension | restriction | substitution))",
8640 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008641 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008642 }
8643}
8644
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008645/**
8646 * xmlSchemaParseSchemaTopLevel:
8647 * @ctxt: a schema validation context
8648 * @schema: the schemas
8649 * @nodes: the list of top level nodes
8650 *
8651 * Returns the internal XML Schema structure built from the resource or
8652 * NULL in case of error
8653 */
8654static void
8655xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8656 xmlSchemaPtr schema, xmlNodePtr nodes)
8657{
8658 xmlNodePtr child;
8659 xmlSchemaAnnotPtr annot;
8660
8661 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8662 return;
8663
8664 child = nodes;
8665 while ((IS_SCHEMA(child, "include")) ||
8666 (IS_SCHEMA(child, "import")) ||
8667 (IS_SCHEMA(child, "redefine")) ||
8668 (IS_SCHEMA(child, "annotation"))) {
8669 if (IS_SCHEMA(child, "annotation")) {
8670 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8671 if (schema->annot == NULL)
8672 schema->annot = annot;
8673 else
8674 xmlSchemaFreeAnnot(annot);
8675 } else if (IS_SCHEMA(child, "import")) {
8676 xmlSchemaParseImport(ctxt, schema, child);
8677 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008678 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008679 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008680 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008681 } else if (IS_SCHEMA(child, "redefine")) {
8682 TODO
8683 }
8684 child = child->next;
8685 }
8686 while (child != NULL) {
8687 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008688 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008689 child = child->next;
8690 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008691 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008692 child = child->next;
8693 } else if (IS_SCHEMA(child, "element")) {
8694 xmlSchemaParseElement(ctxt, schema, child, 1);
8695 child = child->next;
8696 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008697 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008698 child = child->next;
8699 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008700 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008701 child = child->next;
8702 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008703 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008704 child = child->next;
8705 } else if (IS_SCHEMA(child, "notation")) {
8706 xmlSchemaParseNotation(ctxt, schema, child);
8707 child = child->next;
8708 } else {
8709 xmlSchemaPErr2(ctxt, NULL, child,
8710 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008711 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008712 child->name, NULL);
8713 child = child->next;
8714 }
8715 while (IS_SCHEMA(child, "annotation")) {
8716 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8717 if (schema->annot == NULL)
8718 schema->annot = annot;
8719 else
8720 xmlSchemaFreeAnnot(annot);
8721 child = child->next;
8722 }
8723 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008724 ctxt->parentItem = NULL;
8725 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008726}
8727
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008728static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008729xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008730 xmlHashTablePtr *imports,
8731 const xmlChar *nsName)
8732{
8733 xmlSchemaImportPtr ret;
8734
8735 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008736 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008737 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008738 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008739 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8740 NULL, NULL, (xmlNodePtr) ctxt->doc,
8741 "Internal error: failed to build the import table",
8742 NULL);
8743 return (NULL);
8744 }
8745 }
8746 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8747 if (ret == NULL) {
8748 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8749 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008750 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008751 memset(ret, 0, sizeof(xmlSchemaImport));
8752 if (nsName == NULL)
8753 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008754 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008755
8756 return (ret);
8757}
8758
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008759/**
8760 * xmlSchemaNewParserCtxtUseDict:
8761 * @URL: the location of the schema
8762 * @dict: the dictionary to be used
8763 *
8764 * Create an XML Schemas parse context for that file/resource expected
8765 * to contain an XML Schemas file.
8766 *
8767 * Returns the parser context or NULL in case of error
8768 */
8769static xmlSchemaParserCtxtPtr
8770xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8771{
8772 xmlSchemaParserCtxtPtr ret;
8773 /*
8774 if (URL == NULL)
8775 return (NULL);
8776 */
8777
8778 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8779 if (ret == NULL) {
8780 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8781 NULL);
8782 return (NULL);
8783 }
8784 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8785 ret->dict = dict;
8786 xmlDictReference(dict);
8787 if (URL != NULL)
8788 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8789 ret->includes = 0;
8790 return (ret);
8791}
8792
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008793static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008794xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8795{
8796 if (vctxt->pctxt == NULL) {
8797 if (vctxt->schema != NULL)
8798 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8799 else
8800 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8801 if (vctxt->pctxt == NULL) {
8802 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8803 "failed to create a temp. parser context");
8804 return (-1);
8805 }
8806 /* TODO: Pass user data. */
8807 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8808 }
8809 return (0);
8810}
8811
8812static int
8813xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008814 xmlSchemaPtr schema,
8815 xmlNodePtr node,
8816 const xmlChar *nsName,
8817 const xmlChar *location,
8818 xmlDocPtr *doc,
8819 const xmlChar **targetNamespace,
8820 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008821{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008822 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008823 xmlParserCtxtPtr parserCtxt;
8824 xmlSchemaImportPtr import;
8825 const xmlChar *ns;
8826 xmlNodePtr root;
8827
8828 /*
8829 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8830 * <xsi:noNamespaceSchemaLocation>.
8831 */
8832 *doc = NULL;
8833 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008834 * Given that the schemaLocation [attribute] is only a hint, it is open
8835 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008836 * namespace, regardless of the ·actual value· of schemaLocation, but
8837 * such a strategy risks missing useful information when new
8838 * schemaLocations are offered.
8839 *
8840 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8841 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8842 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008843 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008844 */
8845 if (location == NULL) {
8846 /*
8847 * Schema Document Location Strategy:
8848 *
8849 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008850 * either as a resource which is an XML document or a <schema> element
8851 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008852 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008853 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008854 *
8855 * NOTE: Those stategies are not supported, so we will skip.
8856 */
8857 return (0);
8858 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008859 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008860 ns = XML_SCHEMAS_NO_NAMESPACE;
8861 else
8862 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008863
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008864 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008865 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008866 /*
8867 * There was a valid resource for the specified namespace already
8868 * defined, so skip.
8869 * TODO: This might be changed someday to allow import of
8870 * components from multiple documents for a single target namespace.
8871 */
8872 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008873 }
8874 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8875 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8876 else {
8877 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8878 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8879 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008880 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008881 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008882 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008883 * 2 Based on the location URI, identify an existing schema document,
8884 * either as a resource which is an XML document or a <schema> element
8885 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008886 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008887 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008888 * web which is or contains or references a <schema> element;
8889 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8890 *
8891 */
8892 if ((absolute == 0) && (node != NULL)) {
8893 xmlChar *base, *URI;
8894
8895 base = xmlNodeGetBase(node->doc, node);
8896 if (base == NULL) {
8897 URI = xmlBuildURI(location, node->doc->URL);
8898 } else {
8899 URI = xmlBuildURI(location, base);
8900 xmlFree(base);
8901 }
8902 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008903 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008904 xmlFree(URI);
8905 }
8906 }
8907 parserCtxt = xmlNewParserCtxt();
8908 if (parserCtxt == NULL) {
8909 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8910 "allocating a parser context", NULL);
8911 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008912 }
8913 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008914 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008915 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008916 xmlDictReference(parserCtxt->dict);
8917 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008918 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008919 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008920 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008921 * 2.1 The referent is (a fragment of) a resource which is an
8922 * XML document (see clause 1.1), which in turn corresponds to
8923 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008924 * set, which in turn corresponds to a valid schema.
8925 * TODO: What to do with the "fragment" stuff?
8926 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008927 * 2.2 The referent is a <schema> element information item in
8928 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008929 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008930 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008931 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008932 */
8933 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008934 xmlErrorPtr lerr;
8935 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008936 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008937 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008938 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008939 * If the doc is NULL and the parser error is an IO error we
8940 * will assume that the resource could not be located or accessed.
8941 *
8942 * TODO: Try to find specific error codes to react only on
8943 * localisation failures.
8944 *
8945 * TODO, FIXME: Check the spec: is a namespace added to the imported
8946 * namespaces, even if the schemaLocation did not provide
8947 * a resource? I guess so, since omitting the "schemaLocation"
8948 * attribute, imports a namespace as well.
8949 */
8950 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008951 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008952 xmlFreeParserCtxt(parserCtxt);
8953 return(0);
8954 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008955 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008956 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008957 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008958 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 xmlFreeParserCtxt(parserCtxt);
8961 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8962 }
8963 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008964
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008965 root = xmlDocGetRootElement(*doc);
8966 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008968 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008969 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008970 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008971 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008972 xmlFreeDoc(*doc);
8973 *doc = NULL;
8974 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008975 }
8976
8977 xmlSchemaCleanupDoc(pctxt, root);
8978
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008979 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008980 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008981 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008982 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008983 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008984 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985 xmlFreeDoc(*doc);
8986 *doc = NULL;
8987 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008988 }
8989 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008990 /*
8991 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 if (nsName == NULL) {
8994 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008995 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008996 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008997 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008998 "The XML schema to be imported is not expected "
8999 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009000 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009001 xmlFreeDoc(*doc);
9002 *doc = NULL;
9003 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9004 }
9005 } else {
9006 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009007 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009008 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009009 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009010 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009011 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009012 xmlFreeDoc(*doc);
9013 *doc = NULL;
9014 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9015 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009016 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009017 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009018 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009019 "The XML schema to be imported is expected to have a "
9020 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009021 "its target namespace of '%s'",
9022 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009023 xmlFreeDoc(*doc);
9024 *doc = NULL;
9025 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9026 }
9027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009028 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009029 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009030 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9031 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009032 xmlFreeDoc(*doc);
9033 *doc = NULL;
9034 return (-1);
9035 }
9036 import->schemaLocation = location;
9037 import->doc = *doc;
9038 return (0);
9039}
William M. Brack2f2a6632004-08-20 23:09:47 +00009040
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009041static void
9042xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9043 xmlSchemaPtr schema,
9044 const xmlChar *targetNamespace,
9045 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009046{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009047 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009048 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009049
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009050 /*
9051 * Save and reset the context & schema.
9052 */
9053 oldURL = pctxt->URL;
9054 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009055 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009056 oldLocImps = pctxt->localImports;
9057 pctxt->localImports = NULL;
9058 oldNumLocImps = pctxt->nbLocalImports;
9059 pctxt->nbLocalImports = 0;
9060 oldSizeLocImps = pctxt->sizeLocalImports;
9061 pctxt->sizeLocalImports = 0;
9062 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009063 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009064 xmlSchemaClearSchemaDefaults(schema);
9065 oldTNS = schema->targetNamespace;
9066 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009067 if ((targetNamespace != NULL) &&
9068 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9069 /*
9070 * We are parsing the schema for schema!
9071 */
9072 pctxt->isS4S = 1;
9073 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009074 /*
9075 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009076 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009077 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9078 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9079 /*
9080 * Restore the context & schema.
9081 */
9082 schema->flags = oldFlags;
9083 schema->targetNamespace = oldTNS;
9084 if (pctxt->localImports != NULL)
9085 xmlFree((xmlChar *) pctxt->localImports);
9086 pctxt->localImports = oldLocImps;
9087 pctxt->nbLocalImports = oldNumLocImps;
9088 pctxt->sizeLocalImports = oldSizeLocImps;
9089 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009090 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009091}
9092
William M. Brack2f2a6632004-08-20 23:09:47 +00009093/**
9094 * xmlSchemaParseImport:
9095 * @ctxt: a schema validation context
9096 * @schema: the schema being built
9097 * @node: a subtree containing XML Schema informations
9098 *
9099 * parse a XML schema Import definition
9100 * *WARNING* this interface is highly subject to change
9101 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009102 * Returns 0 in case of success, a positive error code if
9103 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009104 */
9105static int
9106xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9107 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009108{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009109 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009110 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009111 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009112 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009113 xmlAttrPtr attr;
9114 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009115 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009116
9117 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9118 return (-1);
9119
9120 /*
9121 * Check for illegal attributes.
9122 */
9123 attr = node->properties;
9124 while (attr != NULL) {
9125 if (attr->ns == NULL) {
9126 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9127 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9128 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009129 xmlSchemaPIllegalAttrErr(ctxt,
9130 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9131 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009132 }
9133 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009134 xmlSchemaPIllegalAttrErr(ctxt,
9135 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9136 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009137 }
9138 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009139 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009140 /*
9141 * Extract and validate attributes.
9142 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009143 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9144 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009145 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009146 xmlSchemaPSimpleTypeErr(ctxt,
9147 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9148 NULL, node,
9149 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009150 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009151 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9152 }
9153
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009154 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9155 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009156 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009157 xmlSchemaPSimpleTypeErr(ctxt,
9158 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9159 NULL, node,
9160 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009161 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009162 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009163 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009164 /*
9165 * And now for the children...
9166 */
9167 child = node->children;
9168 if (IS_SCHEMA(child, "annotation")) {
9169 /*
9170 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009171 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009172 */
9173 child = child->next;
9174 }
9175 if (child != NULL) {
9176 xmlSchemaPContentErr(ctxt,
9177 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9178 NULL, NULL, node, child, NULL,
9179 "(annotation?)");
9180 }
9181 /*
9182 * Apply additional constraints.
9183 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009184 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009185 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009186 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9187 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009188 * targetNamespace [attribute].
9189 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009190 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009191 xmlSchemaPCustomErr(ctxt,
9192 XML_SCHEMAP_SRC_IMPORT_1_1,
9193 NULL, NULL, node,
9194 "The value of the attribute 'namespace' must not match "
9195 "the target namespace '%s' of the importing schema",
9196 schema->targetNamespace);
9197 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9198 }
9199 } else {
9200 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009201 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009202 * <schema> must have a targetNamespace [attribute].
9203 */
9204 if (schema->targetNamespace == NULL) {
9205 xmlSchemaPCustomErr(ctxt,
9206 XML_SCHEMAP_SRC_IMPORT_1_2,
9207 NULL, NULL, node,
9208 "The attribute 'namespace' must be existent if "
9209 "the importing schema has no target namespace",
9210 NULL);
9211 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9212 }
9213 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009214 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009215 * Add the namespace to the list of locally imported namespace.
9216 */
9217 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009218 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009219 sizeof(const xmlChar*));
9220 ctxt->sizeLocalImports = 10;
9221 ctxt->nbLocalImports = 0;
9222 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9223 ctxt->sizeLocalImports *= 2;
9224 ctxt->localImports = (const xmlChar **) xmlRealloc(
9225 (xmlChar **) ctxt->localImports,
9226 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9227 }
9228 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9229 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009230 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009231 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009232 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9233 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009234 schemaLocation, &doc, &targetNamespace, 0);
9235 if (ret != 0) {
9236 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009237 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009238 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009239 } else if (doc != NULL) {
9240 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9241 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009242 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009243
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009244 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009245}
9246
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009247/**
9248 * xmlSchemaParseInclude:
9249 * @ctxt: a schema validation context
9250 * @schema: the schema being built
9251 * @node: a subtree containing XML Schema informations
9252 *
9253 * parse a XML schema Include definition
9254 *
William M. Bracke7091952004-05-11 15:09:58 +00009255 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009256 * 1 in case of success.
9257 */
9258static int
9259xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9260 xmlNodePtr node)
9261{
9262 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009263 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009264 xmlDocPtr doc = NULL;
9265 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009266 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009267 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009268 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009269 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009270
9271
9272 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9273 return (-1);
9274
9275 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009276 * Check for illegal attributes.
9277 */
9278 attr = node->properties;
9279 while (attr != NULL) {
9280 if (attr->ns == NULL) {
9281 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9282 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009283 xmlSchemaPIllegalAttrErr(ctxt,
9284 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9285 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009286 }
9287 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009288 xmlSchemaPIllegalAttrErr(ctxt,
9289 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9290 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009291 }
9292 attr = attr->next;
9293 }
9294 /*
9295 * Extract and validate attributes.
9296 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009297 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009298 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009299 * Preliminary step, extract the URI-Reference for the include and
9300 * make an URI from the base.
9301 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009302 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9303 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009304 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009305 xmlChar *uri = NULL;
9306
9307 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9308 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009309 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009310 base = xmlNodeGetBase(node->doc, node);
9311 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009312 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009313 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009314 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009315 xmlFree(base);
9316 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009317 if (uri == NULL) {
9318 xmlSchemaPErr(ctxt,
9319 node,
9320 XML_SCHEMAP_INTERNAL,
9321 "Internal error: xmlSchemaParseInclude, "
9322 "could not build an URI from the schemaLocation.\n",
9323 NULL, NULL);
9324 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009325 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009326 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9327 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009328 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009329 xmlSchemaPMissingAttrErr(ctxt,
9330 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9331 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009332 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009333 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009334 /*
9335 * And now for the children...
9336 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009337 child = node->children;
9338 while (IS_SCHEMA(child, "annotation")) {
9339 /*
9340 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009341 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009342 */
9343 child = child->next;
9344 }
9345 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009346 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009347 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9348 NULL, NULL, node, child, NULL,
9349 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009350 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009351 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009352 * Report self-inclusion.
9353 */
9354 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9355 xmlSchemaPCustomErr(ctxt,
9356 XML_SCHEMAP_SRC_INCLUDE,
9357 NULL, NULL, node,
9358 "The schema document '%s' cannot include itself.",
9359 schemaLocation);
9360 return (XML_SCHEMAP_SRC_INCLUDE);
9361 }
9362 /*
9363 * Check if this one was already processed to avoid incorrect
9364 * duplicate component errors and infinite circular inclusion.
9365 */
9366 include = schema->includes;
9367 while (include != NULL) {
9368 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9369 targetNamespace = include->origTargetNamespace;
9370 if (targetNamespace == NULL) {
9371 /*
9372 * Chameleon include: skip only if it was build for
9373 * the targetNamespace of the including schema.
9374 */
9375 if (xmlStrEqual(schema->targetNamespace,
9376 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009377 goto check_targetNamespace;
9378 }
9379 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009380 goto check_targetNamespace;
9381 }
9382 }
9383 include = include->next;
9384 }
9385 /*
9386 * First step is to parse the input document into an DOM/Infoset
9387 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009388 */
9389 parserCtxt = xmlNewParserCtxt();
9390 if (parserCtxt == NULL) {
9391 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9392 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009393 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009394 }
9395
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009396 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9397 xmlDictFree(parserCtxt->dict);
9398 parserCtxt->dict = ctxt->dict;
9399 xmlDictReference(parserCtxt->dict);
9400 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009401
9402 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009403 NULL, SCHEMAS_PARSE_OPTIONS);
9404 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009405 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009406 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009407 * TODO: It is not an error for the ·actual value· of the
9408 * schemaLocation [attribute] to fail to resolve it all, in which
9409 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009410 * So do we need a warning report here?
9411 */
9412 xmlSchemaPCustomErr(ctxt,
9413 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009414 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009415 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009416 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009417 }
9418
9419 /*
9420 * Then extract the root of the schema
9421 */
9422 root = xmlDocGetRootElement(doc);
9423 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009424 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009425 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009426 NULL, NULL, node,
9427 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009428 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009429 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009430 }
9431
9432 /*
9433 * Remove all the blank text nodes
9434 */
9435 xmlSchemaCleanupDoc(ctxt, root);
9436
9437 /*
9438 * Check the schemas top level element
9439 */
9440 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009441 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009442 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009443 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009444 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009445 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009446 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009447 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009448
William M. Brack2f2a6632004-08-20 23:09:47 +00009449 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009450 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009451 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9452 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009453 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9454 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009455check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009456 if (targetNamespace != NULL) {
9457 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009458 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009459 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009460 NULL, NULL, node,
9461 "The target namespace of the included schema "
9462 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009463 "has no target namespace",
9464 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009465 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009466 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9467 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009468 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009469 NULL, NULL, node,
9470 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009471 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009472 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009473 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009475 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009476 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009477 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009478 } else
9479 wasConvertingNs = 1;
9480 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009481
9482 if (include != NULL)
9483 goto exit;
9484
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009485 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009486 * URGENT TODO: If the schema is a chameleon-include then copy the
9487 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009488 * of those components, do nothing otherwise.
9489 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009490 * for every destinct including targetNamespace; thus not performant at
9491 * the moment.
9492 * TODO: Check when the namespace in wildcards for chameleons needs
9493 * to be converted: before we built wildcard intersections or after.
9494 */
9495 /*
9496 * Register the include.
9497 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009498 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9499 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009500 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9501 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009502 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009503 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009504 include->next = schema->includes;
9505 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009506 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009507 * TODO: Use the resolved URI for the this location, since it might
9508 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009509 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009510 include->schemaLocation = schemaLocation;
9511 include->doc = doc;
9512 /*
9513 * In case of chameleons, the original target namespace will differ
9514 * from the resulting namespace.
9515 */
9516 include->origTargetNamespace = targetNamespace;
9517 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009518#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009519 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009520 xmlGenericError(xmlGenericErrorContext,
9521 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9522 " into TNS '%s'\n", schemaLocation,
9523 targetNamespace, schema->targetNamespace);
9524 else
9525 xmlGenericError(xmlGenericErrorContext,
9526 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9527 targetNamespace);
9528#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009529 /*
9530 * Compile the included schema.
9531 */
9532 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9533
9534exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009535 /*
9536 * Remove the converting flag.
9537 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009538 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009539 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009540 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009541 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009542
9543exit_invalid:
9544 if (doc != NULL) {
9545 if (include != NULL)
9546 include->doc = NULL;
9547 xmlFreeDoc(doc);
9548 }
9549 return (ctxt->err);
9550
9551exit_failure:
9552 if (doc != NULL) {
9553 if (include != NULL)
9554 include->doc = NULL;
9555 xmlFreeDoc(doc);
9556 }
9557 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009558}
9559
9560/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009561 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009562 * @ctxt: a schema validation context
9563 * @schema: the schema being built
9564 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009565 * @type: the "compositor" type
9566 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009567 *
9568 * parse a XML schema Sequence definition
9569 * *WARNING* this interface is highly subject to change
9570 *
William M. Bracke7091952004-05-11 15:09:58 +00009571 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009572 * 1 in case of success.
9573 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009574static xmlSchemaTreeItemPtr
9575xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9576 xmlNodePtr node, xmlSchemaTypeType type,
9577 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009578{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009579 xmlSchemaModelGroupPtr item;
9580 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009581 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009582 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009583 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009584 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009585
9586 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009587 return (NULL);
9588 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009589 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009590 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009591 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9592 if (item == NULL)
9593 return (NULL);
9594
9595 if (withParticle) {
9596 if (type == XML_SCHEMA_TYPE_ALL) {
9597 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009598 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009599 } else {
9600 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009601 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9602 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9603 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009604 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009605 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9606 /*
9607 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009608 */
9609 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9610 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009611 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009612 particle->children = (xmlSchemaTreeItemPtr) item;
9613 /*
9614 * Check for illegal attributes.
9615 */
9616 attr = node->properties;
9617 while (attr != NULL) {
9618 if (attr->ns == NULL) {
9619 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9620 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9621 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009622 xmlSchemaPIllegalAttrErr(ctxt,
9623 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9624 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009625 }
9626 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009627 xmlSchemaPIllegalAttrErr(ctxt,
9628 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9629 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009630 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009631 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009632 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009633 } else {
9634 /*
9635 * Check for illegal attributes.
9636 */
9637 attr = node->properties;
9638 while (attr != NULL) {
9639 if (attr->ns == NULL) {
9640 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009641 xmlSchemaPIllegalAttrErr(ctxt,
9642 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9643 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009644 }
9645 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009646 xmlSchemaPIllegalAttrErr(ctxt,
9647 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9648 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009649 }
9650 attr = attr->next;
9651 }
9652
William M. Brack2f2a6632004-08-20 23:09:47 +00009653 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009654
William M. Brack2f2a6632004-08-20 23:09:47 +00009655 /*
9656 * Extract and validate attributes.
9657 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009658 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009659 /*
9660 * And now for the children...
9661 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009662 child = node->children;
9663 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009664 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009665 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009666 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009667 oldcontainer = ctxt->container;
9668 ctxt->container = container;
9669 if (type == XML_SCHEMA_TYPE_ALL) {
9670 xmlSchemaParticlePtr part, last = NULL;
9671
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009672 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009673 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9674 schema, child, 0);
9675 if (part != NULL) {
9676 if (part->minOccurs > 1)
9677 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009678 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009679 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9680 if (part->maxOccurs > 1)
9681 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009682 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009683 "Invalid value for maxOccurs (must be 0 or 1)",
9684 NULL);
9685 if (last == NULL)
9686 item->children = (xmlSchemaTreeItemPtr) part;
9687 else
9688 last->next = (xmlSchemaTreeItemPtr) part;
9689 last = part;
9690 }
9691 child = child->next;
9692 }
9693 if (child != NULL) {
9694 xmlSchemaPContentErr(ctxt,
9695 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9696 NULL, NULL, node, child, NULL,
9697 "(annotation?, (annotation?, element*)");
9698 }
9699 } else {
9700 /* choice + sequence */
9701 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9702
9703 while ((IS_SCHEMA(child, "element")) ||
9704 (IS_SCHEMA(child, "group")) ||
9705 (IS_SCHEMA(child, "any")) ||
9706 (IS_SCHEMA(child, "choice")) ||
9707 (IS_SCHEMA(child, "sequence"))) {
9708
9709 if (IS_SCHEMA(child, "element")) {
9710 part = (xmlSchemaTreeItemPtr)
9711 xmlSchemaParseElement(ctxt, schema, child, 0);
9712 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009713 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009714 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9715 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009716 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009717 xmlSchemaParseAny(ctxt, schema, child);
9718 } else if (IS_SCHEMA(child, "choice")) {
9719 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9720 XML_SCHEMA_TYPE_CHOICE, 1);
9721 } else if (IS_SCHEMA(child, "sequence")) {
9722 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9723 XML_SCHEMA_TYPE_SEQUENCE, 1);
9724 }
9725 if (part != NULL) {
9726 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009727 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009728 else
9729 last->next = part;
9730 last = part;
9731 }
9732 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009733 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009734 if (child != NULL) {
9735 xmlSchemaPContentErr(ctxt,
9736 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9737 NULL, NULL, node, child, NULL,
9738 "(annotation?, (element | group | choice | sequence | any)*)");
9739 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009740 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009741 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009742 if (withParticle) {
9743 if ((min == 0) && (max == 0))
9744 return (NULL);
9745 else
9746 return ((xmlSchemaTreeItemPtr) particle);
9747 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009748 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009749}
9750
9751/**
9752 * xmlSchemaParseRestriction:
9753 * @ctxt: a schema validation context
9754 * @schema: the schema being built
9755 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009756 *
9757 * parse a XML schema Restriction definition
9758 * *WARNING* this interface is highly subject to change
9759 *
9760 * Returns the type definition or NULL in case of error
9761 */
9762static xmlSchemaTypePtr
9763xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009764 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009766 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009767 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009768 char buf[30];
9769 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009770 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009771
9772 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9773 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009774 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009775 type = ctxt->ctxtType;
9776 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009777
9778 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009779 * TODO: Is the container needed at all? the anonymous
9780 * items inside should generate unique names already.
9781 */
9782 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009783 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009784 /*
9785 * Check for illegal attributes.
9786 */
9787 attr = node->properties;
9788 while (attr != NULL) {
9789 if (attr->ns == NULL) {
9790 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9791 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009792 xmlSchemaPIllegalAttrErr(ctxt,
9793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9794 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009795 }
9796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009797 xmlSchemaPIllegalAttrErr(ctxt,
9798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9799 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009800 }
9801 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009802 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009803 /*
9804 * Extract and validate attributes.
9805 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009806 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009807 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009808 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009809 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009810 /*
9811 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9812 * among its [children]), the simple type definition which is
9813 * the {content type} of the type definition ·resolved· to by
9814 * the ·actual value· of the base [attribute]"
9815 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009816 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009817 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009818 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009819 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009820 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009821 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009822 XML_SCHEMAP_S4S_ATTR_MISSING,
9823 type, node, "base", NULL);
9824 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009825 /*
9826 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009827 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009828 child = node->children;
9829 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009830 /*
9831 * Add the annotation to the simple type ancestor.
9832 */
9833 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9834 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009835 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009836 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009837 oldcontainer = ctxt->container;
9838 ctxt->container = container;
9839 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9840 /*
9841 * Corresponds to <simpleType><restriction><simpleType>.
9842 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009843 if (IS_SCHEMA(child, "simpleType")) {
9844 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009845 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009846 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009847 * Either the base [attribute] or the simpleType [child] of the
9848 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009849 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009850 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009851 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009852 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009853 "The attribute 'base' and the <simpleType> child are "
9854 "mutually exclusive", NULL);
9855 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009856 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009857 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009858 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009859 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009860 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009861 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009862 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9863 NULL, NULL, node, child,
9864 "Either the attribute 'base' or a <simpleType> child "
9865 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009866 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009867 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9868 /*
9869 * Corresponds to <complexType><complexContent><restriction>...
9870 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009871 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009872 * Model groups <all>, <choice> and <sequence>.
9873 */
9874 if (IS_SCHEMA(child, "all")) {
9875 type->subtypes = (xmlSchemaTypePtr)
9876 xmlSchemaParseModelGroup(ctxt, schema, child,
9877 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009878 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009879 } else if (IS_SCHEMA(child, "choice")) {
9880 type->subtypes = (xmlSchemaTypePtr)
9881 xmlSchemaParseModelGroup(ctxt,
9882 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9883 child = child->next;
9884 } else if (IS_SCHEMA(child, "sequence")) {
9885 type->subtypes = (xmlSchemaTypePtr)
9886 xmlSchemaParseModelGroup(ctxt, schema, child,
9887 XML_SCHEMA_TYPE_SEQUENCE, 1);
9888 child = child->next;
9889 /*
9890 * Model group reference <group>.
9891 */
9892 } else if (IS_SCHEMA(child, "group")) {
9893 type->subtypes = (xmlSchemaTypePtr)
9894 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9895 child = child->next;
9896 }
9897 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009898 /*
9899 * Corresponds to <complexType><simpleContent><restriction>...
9900 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009901 * "1.1 the simple type definition corresponding to the <simpleType>
9902 * among the [children] of <restriction> if there is one;"
9903 */
9904 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009905 /*
9906 * We will store the to-be-restricted simple type in
9907 * type->contentTypeDef *temporarily*.
9908 */
9909 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009910 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009911 if ( type->contentTypeDef == NULL)
9912 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009913 child = child->next;
9914 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009915 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009916
9917 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009918 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009919 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009920 /*
9921 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009922 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009923 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009924
Daniel Veillard01fa6152004-06-29 17:04:39 +00009925 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009926 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009927 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009928 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009929 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9930 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009931 * *Single Facet Value*
9932 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009933 while ((IS_SCHEMA(child, "minInclusive")) ||
9934 (IS_SCHEMA(child, "minExclusive")) ||
9935 (IS_SCHEMA(child, "maxInclusive")) ||
9936 (IS_SCHEMA(child, "maxExclusive")) ||
9937 (IS_SCHEMA(child, "totalDigits")) ||
9938 (IS_SCHEMA(child, "fractionDigits")) ||
9939 (IS_SCHEMA(child, "pattern")) ||
9940 (IS_SCHEMA(child, "enumeration")) ||
9941 (IS_SCHEMA(child, "whiteSpace")) ||
9942 (IS_SCHEMA(child, "length")) ||
9943 (IS_SCHEMA(child, "maxLength")) ||
9944 (IS_SCHEMA(child, "minLength"))) {
9945 facet = xmlSchemaParseFacet(ctxt, schema, child);
9946 if (facet != NULL) {
9947 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009948 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009949 else
9950 lastfacet->next = facet;
9951 lastfacet = facet;
9952 lastfacet->next = NULL;
9953 }
9954 child = child->next;
9955 }
9956 /*
9957 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009958 */
9959 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009960 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9961
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009962 facet = type->facets;
9963 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009964 facetLink = (xmlSchemaFacetLinkPtr)
9965 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009966 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009967 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009968 xmlFree(facetLink);
9969 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009970 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009971 facetLink->facet = facet;
9972 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009973 if (lastFacetLink == NULL)
9974 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009975 else
9976 lastFacetLink->next = facetLink;
9977 lastFacetLink = facetLink;
9978 facet = facet->next;
9979 } while (facet != NULL);
9980 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009981 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009982 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9983 /*
9984 * Attribute uses/declarations.
9985 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009986 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009987 /*
9988 * Attribute wildcard.
9989 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009990 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009991 type->attributeWildcard =
9992 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009993 child = child->next;
9994 }
9995 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009996 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009997 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9998 xmlSchemaPContentErr(ctxt,
9999 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010000 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010001 "annotation?, (group | all | choice | sequence)?, "
10002 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010003 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010004 xmlSchemaPContentErr(ctxt,
10005 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010006 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010007 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10008 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10009 "length | minLength | maxLength | enumeration | whiteSpace | "
10010 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10011 } else {
10012 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010013 xmlSchemaPContentErr(ctxt,
10014 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010015 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010016 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10017 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10018 "length | minLength | maxLength | enumeration | whiteSpace | "
10019 "pattern)*))");
10020 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010021 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010022 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010023 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010024}
10025
10026/**
10027 * xmlSchemaParseExtension:
10028 * @ctxt: a schema validation context
10029 * @schema: the schema being built
10030 * @node: a subtree containing XML Schema informations
10031 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010032 * Parses an <extension>, which is found inside a
10033 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010034 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010035 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010036 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010037 */
10038static xmlSchemaTypePtr
10039xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010040 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010041{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010042 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010043 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010044 char buf[30];
10045 const xmlChar *oldcontainer, *container;
10046 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010047
10048 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10049 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010050 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010051 type = ctxt->ctxtType;
10052 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010053
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010054 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10055 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10056 /*
10057 * Check for illegal attributes.
10058 */
10059 attr = node->properties;
10060 while (attr != NULL) {
10061 if (attr->ns == NULL) {
10062 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10063 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010064 xmlSchemaPIllegalAttrErr(ctxt,
10065 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10066 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010067 }
10068 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010069 xmlSchemaPIllegalAttrErr(ctxt,
10070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10071 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010072 }
10073 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010074 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010075
10076 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010077
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010078 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010079 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010080 */
10081 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010082 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10083 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010084 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010085 XML_SCHEMAP_S4S_ATTR_MISSING,
10086 NULL, node, "base", NULL);
10087 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010088 /*
10089 * And now for the children...
10090 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010091 child = node->children;
10092 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010093 /*
10094 * Add the annotation to the type ancestor.
10095 */
10096 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10097 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010098 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010099 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010100 oldcontainer = ctxt->container;
10101 ctxt->container = container;
10102 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10103 /*
10104 * Corresponds to <complexType><complexContent><extension>... and:
10105 *
10106 * Model groups <all>, <choice>, <sequence> and <group>.
10107 */
10108 if (IS_SCHEMA(child, "all")) {
10109 type->subtypes = (xmlSchemaTypePtr)
10110 xmlSchemaParseModelGroup(ctxt, schema,
10111 child, XML_SCHEMA_TYPE_ALL, 1);
10112 child = child->next;
10113 } else if (IS_SCHEMA(child, "choice")) {
10114 type->subtypes = (xmlSchemaTypePtr)
10115 xmlSchemaParseModelGroup(ctxt, schema,
10116 child, XML_SCHEMA_TYPE_CHOICE, 1);
10117 child = child->next;
10118 } else if (IS_SCHEMA(child, "sequence")) {
10119 type->subtypes = (xmlSchemaTypePtr)
10120 xmlSchemaParseModelGroup(ctxt, schema,
10121 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10122 child = child->next;
10123 } else if (IS_SCHEMA(child, "group")) {
10124 type->subtypes = (xmlSchemaTypePtr)
10125 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10126 child = child->next;
10127 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010128 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010129 if (child != NULL) {
10130 /*
10131 * Attribute uses/declarations.
10132 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010133 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010134 /*
10135 * Attribute wildcard.
10136 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010137 if (IS_SCHEMA(child, "anyAttribute")) {
10138 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010139 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10140 child = child->next;
10141 }
10142 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010143 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010144 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10145 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010146 xmlSchemaPContentErr(ctxt,
10147 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010148 NULL, NULL, node, child, NULL,
10149 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010150 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010151 } else {
10152 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010153 xmlSchemaPContentErr(ctxt,
10154 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010155 NULL, NULL, node, child, NULL,
10156 "(annotation?, ((attribute | attributeGroup)*, "
10157 "anyAttribute?))");
10158 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010159 }
10160 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010161 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010162}
10163
10164/**
10165 * xmlSchemaParseSimpleContent:
10166 * @ctxt: a schema validation context
10167 * @schema: the schema being built
10168 * @node: a subtree containing XML Schema informations
10169 *
10170 * parse a XML schema SimpleContent definition
10171 * *WARNING* this interface is highly subject to change
10172 *
10173 * Returns the type definition or NULL in case of error
10174 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010175static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010176xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10177 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010178{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010179 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010180 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010181 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010182
10183 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010184 return (-1);
10185 /* Not a component, don't create it. */
10186 type = ctxt->ctxtType;
10187 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10188 /*
10189 * Check for illegal attributes.
10190 */
10191 attr = node->properties;
10192 while (attr != NULL) {
10193 if (attr->ns == NULL) {
10194 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010195 xmlSchemaPIllegalAttrErr(ctxt,
10196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10197 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010198 }
10199 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010200 xmlSchemaPIllegalAttrErr(ctxt,
10201 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10202 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010203 }
10204 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010205 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010206
10207 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010208
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010209 /*
10210 * And now for the children...
10211 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010212 child = node->children;
10213 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010214 /*
10215 * Add the annotation to the complex type ancestor.
10216 */
10217 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10218 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010219 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010220 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010221 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010222 xmlSchemaParseRestriction(ctxt, schema, child,
10223 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010225 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010226 xmlSchemaParseExtension(ctxt, schema, child,
10227 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010228 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010229 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010230 if (child != NULL) {
10231 xmlSchemaPContentErr(ctxt,
10232 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010233 NULL, NULL, node, child, NULL,
10234 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010235 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010236 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010237}
10238
10239/**
10240 * xmlSchemaParseComplexContent:
10241 * @ctxt: a schema validation context
10242 * @schema: the schema being built
10243 * @node: a subtree containing XML Schema informations
10244 *
10245 * parse a XML schema ComplexContent definition
10246 * *WARNING* this interface is highly subject to change
10247 *
10248 * Returns the type definition or NULL in case of error
10249 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010250static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010251xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10252 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010253{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010254 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010255 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010256 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010257
10258 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010259 return (-1);
10260 /* Not a component, don't create it. */
10261 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010262 /*
10263 * Check for illegal attributes.
10264 */
10265 attr = node->properties;
10266 while (attr != NULL) {
10267 if (attr->ns == NULL) {
10268 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010269 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010270 {
10271 xmlSchemaPIllegalAttrErr(ctxt,
10272 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10273 NULL, NULL, attr);
10274 }
10275 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10276 xmlSchemaPIllegalAttrErr(ctxt,
10277 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10278 NULL, NULL, attr);
10279 }
10280 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010281 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010282
10283 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10284
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010285 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010286 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010287 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010288 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10289 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10290 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010291 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010292 child = node->children;
10293 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010294 /*
10295 * Add the annotation to the complex type ancestor.
10296 */
10297 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10298 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010299 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010300 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010301 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010302 xmlSchemaParseRestriction(ctxt, schema, child,
10303 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010304 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010305 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010306 xmlSchemaParseExtension(ctxt, schema, child,
10307 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010308 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010309 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010310 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010311 xmlSchemaPContentErr(ctxt,
10312 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10313 NULL, NULL, node, child,
10314 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010315 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010316 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010317}
10318
10319/**
10320 * xmlSchemaParseComplexType:
10321 * @ctxt: a schema validation context
10322 * @schema: the schema being built
10323 * @node: a subtree containing XML Schema informations
10324 *
10325 * parse a XML schema Complex Type definition
10326 * *WARNING* this interface is highly subject to change
10327 *
10328 * Returns the type definition or NULL in case of error
10329 */
10330static xmlSchemaTypePtr
10331xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010332 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010333{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010334 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010335 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010336 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010337 xmlAttrPtr attr;
10338 const xmlChar *attrValue;
10339 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010340 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010341 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010342
Daniel Veillard4255d502002-04-16 15:50:10 +000010343
10344 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10345 return (NULL);
10346
Daniel Veillard01fa6152004-06-29 17:04:39 +000010347 ctxtType = ctxt->ctxtType;
10348
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010349 if (topLevel) {
10350 attr = xmlSchemaGetPropNode(node, "name");
10351 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010352 xmlSchemaPMissingAttrErr(ctxt,
10353 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010354 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010355 } else if (xmlSchemaPValAttrNode(ctxt,
10356 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010357 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10358 return (NULL);
10359 }
10360 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010361
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010362 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010363 /*
10364 * Parse as local complex type definition.
10365 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010366 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010367 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10368 if (type == NULL)
10369 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010370 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010371 type->node = node;
10372 type->type = XML_SCHEMA_TYPE_COMPLEX;
10373 /*
10374 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010375 */
10376 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010377 /*
10378 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010379 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010380 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010381 if (type == NULL)
10382 return (NULL);
10383 type->node = node;
10384 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010385 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010386 }
10387 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010388 /*
10389 * Handle attributes.
10390 */
10391 attr = node->properties;
10392 while (attr != NULL) {
10393 if (attr->ns == NULL) {
10394 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10395 /*
10396 * Attribute "id".
10397 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010398 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10399 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010400 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10401 /*
10402 * Attribute "mixed".
10403 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010404 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010405 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010406 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10407 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010408 /*
10409 * Attributes of global complex type definitions.
10410 */
10411 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10412 /* Pass. */
10413 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10414 /*
10415 * Attribute "abstract".
10416 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010417 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10418 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010419 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10420 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10421 /*
10422 * Attribute "final".
10423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010424 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010425 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010426 if (xmlSchemaPValAttrBlockFinal(attrValue,
10427 &(type->flags),
10428 -1,
10429 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10430 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10431 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010432 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010433 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010434 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010435 type, (xmlNodePtr) attr, NULL,
10436 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010437 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010438 } else
10439 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010440 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10441 /*
10442 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010443 */
10444 attrValue = xmlSchemaGetNodeContent(ctxt,
10445 (xmlNodePtr) attr);
10446 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010447 -1,
10448 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010449 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010450 -1, -1, -1) != 0) {
10451 xmlSchemaPSimpleTypeErr(ctxt,
10452 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010453 type, (xmlNodePtr) attr, NULL,
10454 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010455 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010456 } else
10457 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010458 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010459 xmlSchemaPIllegalAttrErr(ctxt,
10460 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010461 &des, type, attr);
10462 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010463 } else {
10464 xmlSchemaPIllegalAttrErr(ctxt,
10465 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010466 &des, type, attr);
10467 }
10468 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010469 xmlSchemaPIllegalAttrErr(ctxt,
10470 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10471 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010472 }
10473 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010475 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010476 /*
10477 * Apply default "block" values.
10478 */
10479 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10480 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10481 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10482 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10483 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010484 if (! final) {
10485 /*
10486 * Apply default "block" values.
10487 */
10488 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10489 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10490 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10491 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10492 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010493 /*
10494 * And now for the children...
10495 */
10496 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010497 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010498 child = node->children;
10499 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010500 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10501 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010502 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010503 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010504 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010505 /*
10506 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010507 * Specifying mixed='true' when the <simpleContent>
10508 * alternative is chosen has no effect
10509 */
William M. Bracke7091952004-05-11 15:09:58 +000010510 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10511 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010512 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010513 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010514 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010515 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10516 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010517 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010518 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010519 /*
10520 * SPEC
10521 * "...the third alternative (neither <simpleContent> nor
10522 * <complexContent>) is chosen. This case is understood as shorthand
10523 * for complex content restricting the ·ur-type definition·, and the
10524 * details of the mappings should be modified as necessary.
10525 */
10526 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10527 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010528 /*
10529 * Parse model groups.
10530 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010531 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010532 type->subtypes = (xmlSchemaTypePtr)
10533 xmlSchemaParseModelGroup(ctxt, schema, child,
10534 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010535 child = child->next;
10536 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010537 type->subtypes = (xmlSchemaTypePtr)
10538 xmlSchemaParseModelGroup(ctxt, schema, child,
10539 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010540 child = child->next;
10541 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010542 type->subtypes = (xmlSchemaTypePtr)
10543 xmlSchemaParseModelGroup(ctxt, schema, child,
10544 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010545 child = child->next;
10546 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010547 type->subtypes = (xmlSchemaTypePtr)
10548 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010549 child = child->next;
10550 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010551 /*
10552 * Parse attribute decls/refs.
10553 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010554 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010555 /*
10556 * Parse attribute wildcard.
10557 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010558 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010559 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10560 child = child->next;
10561 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010562 }
10563 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010564 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010565 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010566 &des, type, node, child,
10567 NULL, "(annotation?, (simpleContent | complexContent | "
10568 "((group | all | choice | sequence)?, ((attribute | "
10569 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010570 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010571 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010572 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010573 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010574 return (type);
10575}
10576
Daniel Veillard4255d502002-04-16 15:50:10 +000010577/**
10578 * xmlSchemaParseSchema:
10579 * @ctxt: a schema validation context
10580 * @node: a subtree containing XML Schema informations
10581 *
10582 * parse a XML schema definition from a node set
10583 * *WARNING* this interface is highly subject to change
10584 *
10585 * Returns the internal XML Schema structure built from the resource or
10586 * NULL in case of error
10587 */
10588static xmlSchemaPtr
10589xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10590{
10591 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010592 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010593 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010594 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010595
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010596 /*
10597 * This one is called by xmlSchemaParse only and is used if
10598 * the schema to be parsed was specified via the API; i.e. not
10599 * automatically by the validated instance document.
10600 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010601 if ((ctxt == NULL) || (node == NULL))
10602 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010603 nberrors = ctxt->nberrors;
10604 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010605 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010606 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010607 xmlSchemaImportPtr import;
10608
Daniel Veillard4255d502002-04-16 15:50:10 +000010609 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010610 if (schema == NULL)
10611 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010612 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010613 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010614 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010615 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10616 /*
10617 * TODO: Should we proceed with an invalid target namespace?
10618 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010619 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010620 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10621 /*
10622 * We are parsing the schema for schema!
10623 */
10624 ctxt->isS4S = 1;
10625 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010626 } else {
10627 schema->targetNamespace = NULL;
10628 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010629 /*
10630 * Add the current ns name and location to the import table;
10631 * this is needed to have a consistent mechanism, regardless
10632 * if all schemata are constructed dynamically fired by the
10633 * instance or if the schema to be used was specified via
10634 * the API.
10635 */
10636 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10637 schema->targetNamespace);
10638 if (import == NULL) {
10639 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10640 NULL, NULL, (xmlNodePtr) ctxt->doc,
10641 "Internal error: xmlSchemaParseSchema, "
10642 "failed to add an import entry", NULL);
10643 xmlSchemaFree(schema);
10644 schema = NULL;
10645 return (NULL);
10646 }
10647 import->schemaLocation = ctxt->URL;
10648 /*
10649 * NOTE: We won't set the doc here, otherwise it will be freed
10650 * if the import struct is freed.
10651 * import->doc = ctxt->doc;
10652 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010653 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010654 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10655 } else {
10656 xmlDocPtr doc;
10657
10658 doc = node->doc;
10659
10660 if ((doc != NULL) && (doc->URL != NULL)) {
10661 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10662 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010663 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010664 } else {
10665 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10666 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010667 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010668 }
10669 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010670 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010671 if (ctxt->nberrors != 0) {
10672 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010673 xmlSchemaFree(schema);
10674 schema = NULL;
10675 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010676 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010677 if (schema != NULL)
10678 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010679 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010680#ifdef DEBUG
10681 if (schema == NULL)
10682 xmlGenericError(xmlGenericErrorContext,
10683 "xmlSchemaParse() failed\n");
10684#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010685 return (schema);
10686}
10687
10688/************************************************************************
10689 * *
10690 * Validating using Schemas *
10691 * *
10692 ************************************************************************/
10693
10694/************************************************************************
10695 * *
10696 * Reading/Writing Schemas *
10697 * *
10698 ************************************************************************/
10699
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010700#if 0 /* Will be enabled if it is clear what options are needed. */
10701/**
10702 * xmlSchemaParserCtxtSetOptions:
10703 * @ctxt: a schema parser context
10704 * @options: a combination of xmlSchemaParserOption
10705 *
10706 * Sets the options to be used during the parse.
10707 *
10708 * Returns 0 in case of success, -1 in case of an
10709 * API error.
10710 */
10711static int
10712xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10713 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010714
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010715{
10716 int i;
10717
10718 if (ctxt == NULL)
10719 return (-1);
10720 /*
10721 * WARNING: Change the start value if adding to the
10722 * xmlSchemaParseOption.
10723 */
10724 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10725 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010726 return (-1);
10727 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010728 }
10729 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010730 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010731}
10732
10733/**
10734 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010735 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010736 *
10737 * Returns the option combination of the parser context.
10738 */
10739static int
10740xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010741
10742{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010743 if (ctxt == NULL)
10744 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010745 else
10746 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010747}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010748#endif
10749
Daniel Veillard4255d502002-04-16 15:50:10 +000010750/**
10751 * xmlSchemaNewParserCtxt:
10752 * @URL: the location of the schema
10753 *
10754 * Create an XML Schemas parse context for that file/resource expected
10755 * to contain an XML Schemas file.
10756 *
10757 * Returns the parser context or NULL in case of error
10758 */
10759xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010760xmlSchemaNewParserCtxt(const char *URL)
10761{
Daniel Veillard4255d502002-04-16 15:50:10 +000010762 xmlSchemaParserCtxtPtr ret;
10763
10764 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010765 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010766
10767 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10768 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010769 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010770 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010771 return (NULL);
10772 }
10773 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010774 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010775 ret->dict = xmlDictCreate();
10776 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010777 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010778 return (ret);
10779}
10780
10781/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010782 * xmlSchemaNewMemParserCtxt:
10783 * @buffer: a pointer to a char array containing the schemas
10784 * @size: the size of the array
10785 *
10786 * Create an XML Schemas parse context for that memory buffer expected
10787 * to contain an XML Schemas file.
10788 *
10789 * Returns the parser context or NULL in case of error
10790 */
10791xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010792xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10793{
Daniel Veillard6045c902002-10-09 21:13:59 +000010794 xmlSchemaParserCtxtPtr ret;
10795
10796 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010797 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010798
10799 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10800 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010801 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010802 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010803 return (NULL);
10804 }
10805 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10806 ret->buffer = buffer;
10807 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010808 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010809 return (ret);
10810}
10811
10812/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010813 * xmlSchemaNewDocParserCtxt:
10814 * @doc: a preparsed document tree
10815 *
10816 * Create an XML Schemas parse context for that document.
10817 * NB. The document may be modified during the parsing process.
10818 *
10819 * Returns the parser context or NULL in case of error
10820 */
10821xmlSchemaParserCtxtPtr
10822xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10823{
10824 xmlSchemaParserCtxtPtr ret;
10825
10826 if (doc == NULL)
10827 return (NULL);
10828
10829 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10830 if (ret == NULL) {
10831 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10832 NULL);
10833 return (NULL);
10834 }
10835 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10836 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010837 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010838 /* The application has responsibility for the document */
10839 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010840
10841 return (ret);
10842}
10843
10844/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010845 * xmlSchemaFreeParserCtxt:
10846 * @ctxt: the schema parser context
10847 *
10848 * Free the resources associated to the schema parser context
10849 */
10850void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010851xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10852{
Daniel Veillard4255d502002-04-16 15:50:10 +000010853 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010854 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010855 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010856 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010857 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010858 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010859 xmlFree(ctxt->assemble);
10860 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010861 if (ctxt->vctxt != NULL) {
10862 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10863 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010864 if (ctxt->localImports != NULL)
10865 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010866 if (ctxt->substGroups != NULL)
10867 xmlHashFree(ctxt->substGroups,
10868 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010869 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010870 xmlFree(ctxt);
10871}
10872
10873/************************************************************************
10874 * *
10875 * Building the content models *
10876 * *
10877 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010878
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010879static void
10880xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000010881 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010882{
Daniel Veillarda980bef2005-07-18 21:34:03 +000010883 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010884 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010885 xmlSchemaSubstGroupPtr substGroup;
10886 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010887
10888 elemDecl = (xmlSchemaElementPtr) particle->children;
10889 /*
10890 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010891 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010892 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000010893 if (end == NULL)
10894 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010895 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10896 if (substGroup == NULL) {
10897 xmlSchemaPErr(pctxt, GET_NODE(particle),
10898 XML_SCHEMAP_INTERNAL,
10899 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10900 "declaration is marked having a subst. group but none "
10901 "available.\n", elemDecl->name, NULL);
10902 return;
10903 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000010904 if (counter >= 0) {
10905 /*
10906 * NOTE that we put the declaration in, even if it's abstract,
10907 */
10908 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
10909 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10910 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10911 /*
10912 * Add subst. group members.
10913 */
10914 for (i = 0; i < substGroup->members->nbItems; i++) {
10915 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10916 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10917 member->name, member->targetNamespace, member);
10918 }
10919 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010920 /*
10921 * NOTE that we put the declaration in, even if it's abstract,
10922 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010923 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010924 xmlAutomataNewTransition2(pctxt->am,
10925 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010926 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10927 /*
10928 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010929 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010930 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010931 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000010932 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
10933 member->name, member->targetNamespace,
10934 1, 1, member);
10935 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010936 }
10937 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010938 xmlAutomataStatePtr hop;
10939 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10940 UNBOUNDED : particle->maxOccurs - 1;
10941 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10942
10943 counter =
10944 xmlAutomataNewCounter(pctxt->am, minOccurs,
10945 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010946 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010947
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010948 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010949 xmlAutomataNewTransition2(pctxt->am,
10950 start, NULL,
10951 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010952 hop);
10953 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000010954 * Add subst. group members.
10955 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010956 for (i = 0; i < substGroup->members->nbItems; i++) {
10957 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10958 xmlAutomataNewEpsilon(pctxt->am,
10959 xmlAutomataNewTransition2(pctxt->am,
10960 start, NULL,
10961 member->name, member->targetNamespace, member),
10962 hop);
10963 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010964 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10965 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10966 }
10967 if (particle->minOccurs == 0)
10968 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010969 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010970}
10971
10972static void
10973xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10974 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010975{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010976 if (((xmlSchemaElementPtr) particle->children)->flags &
10977 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010978 /*
10979 * Substitution groups.
10980 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000010981 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010982 } else {
10983 xmlSchemaElementPtr elemDecl;
10984 xmlAutomataStatePtr start;
10985
10986 elemDecl = (xmlSchemaElementPtr) particle->children;
10987
10988 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010989 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010990 if (particle->maxOccurs == 1) {
10991 start = ctxt->state;
10992 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000010993 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10994 } else if ((particle->maxOccurs >= UNBOUNDED) &&
10995 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010996 /* Special case. */
10997 start = ctxt->state;
10998 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10999 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011000 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011001 } else {
11002 int counter;
11003 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11004 UNBOUNDED : particle->maxOccurs - 1;
11005 int minOccurs = particle->minOccurs < 1 ?
11006 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011007
11008 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011009 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11010 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11011 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11012 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11013 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11014 NULL, counter);
11015 }
11016 if (particle->minOccurs == 0)
11017 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11018 }
11019}
11020
Daniel Veillard4255d502002-04-16 15:50:10 +000011021/**
11022 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011023 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011024 * @particle: the particle component
11025 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011026 *
11027 * Generate the automata sequence needed for that type
11028 */
11029static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011030xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011031 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011032 const xmlChar * name)
11033{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011034 if (particle == NULL) {
11035 xmlSchemaPErr(ctxt, NULL,
11036 XML_SCHEMAP_INTERNAL,
11037 "Internal error: xmlSchemaBuildAContentModel, "
11038 "particle is NULL.\n", NULL, NULL);
11039 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011040 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011041 if (particle->children == NULL) {
11042 xmlSchemaPErr(ctxt, GET_NODE(particle),
11043 XML_SCHEMAP_INTERNAL,
11044 "Internal error: xmlSchemaBuildAContentModel, "
11045 "no term on particle.\n", NULL, NULL);
11046 return;
11047 }
11048
11049 switch (particle->children->type) {
11050 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011051 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011052 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011053 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011054
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011055 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011056
Daniel Veillardc0826a72004-08-10 14:17:33 +000011057 start = ctxt->state;
11058 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011059
11060 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011061 if (wild->any == 1) {
11062 /*
11063 * We need to add both transitions:
11064 *
11065 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011066 */
11067 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011068 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011069 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011070 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11071 /*
11072 * 2. the {"*"} for elements in no namespace.
11073 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011074 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011075 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011076 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011077 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11078
11079 } else if (wild->nsSet != NULL) {
11080 ns = wild->nsSet;
11081 do {
11082 ctxt->state = start;
11083 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011084 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011085 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11086 ns = ns->next;
11087 } while (ns != NULL);
11088
11089 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011090
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011091 /*
11092 * Lead nodes with the negated namespace to the sink-state
11093 * {"*", "##other"}.
11094 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011095 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011096 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011097 /*
11098 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011099 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011100 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011101 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011102 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011103 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011104 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011105 } else {
11106 int counter;
11107 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011108 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011109 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011110 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011111 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011112
Daniel Veillardc0826a72004-08-10 14:17:33 +000011113 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011114 hop = xmlAutomataNewState(ctxt->am);
11115 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011116 ctxt->state =
11117 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011118 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011119 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011120 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011121 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011122 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011123 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011124 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011125 ns = wild->nsSet;
11126 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011127 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011128 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011129 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011130 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11131 ns = ns->next;
11132 } while (ns != NULL);
11133
11134 } else if (wild->negNsSet != NULL) {
Daniel Veillard9efc4762005-07-19 14:33:55 +000011135 ctxt->state = xmlAutomataNewNegTrans(ctxt->am,
11136 start, hop, BAD_CAST "*", wild->negNsSet->value,
11137 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011138 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011139 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11140 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11141 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011142 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011143 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011144 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011145 ctxt->state = end;
11146 break;
11147 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011148 case XML_SCHEMA_TYPE_ELEMENT:
11149 xmlSchemaBuildContentModelForElement(ctxt, particle);
11150 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011151 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011152 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011153
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011154 /*
11155 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011156 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011157 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011158 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11159 sub = particle->children->children;
11160 while (sub != NULL) {
11161 xmlSchemaBuildAContentModel(ctxt,
11162 (xmlSchemaParticlePtr) sub, name);
11163 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011164 }
11165 } else {
11166 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011167
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011168 if (particle->maxOccurs >= UNBOUNDED) {
11169 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011170 xmlAutomataStatePtr tmp;
11171 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011172
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011173 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011174 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011175 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011176
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011177 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011178 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011179
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011180 sub = particle->children->children;
11181 while (sub != NULL) {
11182 xmlSchemaBuildAContentModel(ctxt,
11183 (xmlSchemaParticlePtr) sub, name);
11184 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011185 }
11186 tmp = ctxt->state;
11187 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11188 oldstate, counter);
11189 ctxt->state =
11190 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11191 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011192
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011193 } else {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011194 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11195 oldstate, NULL);
11196 oldstate = ctxt->state;
11197
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011198 sub = particle->children->children;
11199 while (sub != NULL) {
11200 xmlSchemaBuildAContentModel(ctxt,
11201 (xmlSchemaParticlePtr) sub, name);
11202 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011203 }
11204 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11205 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011206 /*
11207 * epsilon needed to block previous trans from
11208 * being allowed to enter back from another
11209 * construct
11210 */
11211 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11212 ctxt->state, NULL);
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 }
11217 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011218 } else if ((particle->maxOccurs > 1)
11219 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011220 xmlAutomataStatePtr tmp;
11221 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011222
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011223 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011224 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011225 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011226
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011227 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011228 particle->minOccurs - 1,
11229 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011230
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011231 sub = particle->children->children;
11232 while (sub != NULL) {
11233 xmlSchemaBuildAContentModel(ctxt,
11234 (xmlSchemaParticlePtr) sub, name);
11235 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011236 }
11237 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011238 xmlAutomataNewCountedTrans(ctxt->am,
11239 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011240 ctxt->state =
11241 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11242 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011243 if (particle->minOccurs == 0) {
11244 xmlAutomataNewEpsilon(ctxt->am,
11245 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011246 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011247 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011248 sub = particle->children->children;
11249 while (sub != NULL) {
11250 xmlSchemaBuildAContentModel(ctxt,
11251 (xmlSchemaParticlePtr) sub, name);
11252 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011253 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011254 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011255 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11256 ctxt->state);
11257 }
11258 }
11259 }
11260 break;
11261 }
11262 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011263 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011264 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011265
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011266 start = ctxt->state;
11267 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011268
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011269 /*
11270 * iterate over the subtypes and remerge the end with an
11271 * epsilon transition
11272 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011273 if (particle->maxOccurs == 1) {
11274 sub = particle->children->children;
11275 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011276 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011277 xmlSchemaBuildAContentModel(ctxt,
11278 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011279 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011280 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011281 }
11282 } else {
11283 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011284 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011285 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11286 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011287 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011288 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011289
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011290 /*
11291 * use a counter to keep track of the number of transtions
11292 * which went through the choice.
11293 */
11294 counter =
Daniel Veillardafc05b62005-07-17 06:11:19 +000011295 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011296 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011297 base = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011298
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011299 sub = particle->children->children;
11300 while (sub != NULL) {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011301 ctxt->state = base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011302 xmlSchemaBuildAContentModel(ctxt,
11303 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011304 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011305 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011306 }
Daniel Veillardafc05b62005-07-17 06:11:19 +000011307 xmlAutomataNewEpsilon(ctxt->am, start, base);
11308 xmlAutomataNewCountedTrans(ctxt->am, hop, base, counter);
11309 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011310 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011311 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011312 xmlAutomataNewEpsilon(ctxt->am, start, end);
11313 }
11314 ctxt->state = end;
11315 break;
11316 }
11317 case XML_SCHEMA_TYPE_ALL:{
Daniel Veillarda980bef2005-07-18 21:34:03 +000011318 xmlAutomataStatePtr start, hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011319 xmlSchemaParticlePtr sub;
11320 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011321 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011322
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011323 sub = (xmlSchemaParticlePtr) particle->children->children;
11324 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011325 break;
11326 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011327 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011328 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011329
11330 elemDecl = (xmlSchemaElementPtr) sub->children;
11331 if (elemDecl == NULL) {
11332 xmlSchemaPErr(ctxt, NULL,
11333 XML_SCHEMAP_INTERNAL,
11334 "Internal error: xmlSchemaBuildAContentModel, "
11335 "<element> particle a NULL term.\n", NULL, NULL);
11336 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011337 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011338 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011339 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011340 * {particles} of the group must be 0 or 1; this is
11341 * already ensured during the parse of the content of
11342 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011343 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011344 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11345 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011346
Daniel Veillarda980bef2005-07-18 21:34:03 +000011347 /*
11348 * This is an abstract group, we need to share
11349 * the same counter for all the element transitions
11350 * derived from the group
11351 */
11352 counter = xmlAutomataNewCounter(ctxt->am,
11353 sub->minOccurs, sub->maxOccurs);
11354 xmlSchemaBuildContentModelForSubstGroup(ctxt,
11355 sub, counter, ctxt->state);
11356 } else {
11357 if ((sub->minOccurs == 1) &&
11358 (sub->maxOccurs == 1)) {
11359 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11360 ctxt->state,
11361 elemDecl->name,
11362 elemDecl->targetNamespace,
11363 1, 1, elemDecl);
11364 } else if ((sub->minOccurs == 0) &&
11365 (sub->maxOccurs == 1)) {
11366
11367 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11368 ctxt->state,
11369 elemDecl->name,
11370 elemDecl->targetNamespace,
11371 0,
11372 1,
11373 elemDecl);
11374 }
11375 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011376 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011377 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011378 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011379 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011380 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011381 break;
11382 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011383 default:
11384 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011385 "Internal error: xmlSchemaBuildAContentModel, found "
11386 "unexpected term of type %d in content model of complex "
11387 "type '%s'.\n",
11388 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011389 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011390 }
11391}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011392
Daniel Veillard4255d502002-04-16 15:50:10 +000011393/**
11394 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011395 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011396 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011397 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011398 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011399 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011400 */
11401static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011402xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011403 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011404 const xmlChar * name)
11405{
Daniel Veillard4255d502002-04-16 15:50:10 +000011406 xmlAutomataStatePtr start;
11407
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011408 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11409 (type->contModel != NULL) ||
11410 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11411 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011412 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011413
11414#ifdef DEBUG_CONTENT
11415 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011416 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011417#endif
11418
Daniel Veillard4255d502002-04-16 15:50:10 +000011419 ctxt->am = xmlNewAutomata();
11420 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011421 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011422 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011423 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011424 }
11425 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011426 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011427 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011428 type->contModel = xmlAutomataCompile(ctxt->am);
11429 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011430 xmlSchemaPCustomErr(ctxt,
11431 XML_SCHEMAP_INTERNAL,
11432 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011433 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011434 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011435 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011436 XML_SCHEMAP_NOT_DETERMINISTIC,
11437 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011438 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011439 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011440 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011441#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011442 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011443 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011444 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011445#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011446 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011447 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011448 xmlFreeAutomata(ctxt->am);
11449 ctxt->am = NULL;
11450}
11451
11452/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011453 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011454 * @elem: the schema element context
11455 * @ctxt: the schema parser context
11456 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011457 * Resolves the references of an element declaration
11458 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011459 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011460 */
11461static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011462xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011463 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011464 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011465 const xmlChar * context ATTRIBUTE_UNUSED,
11466 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011467{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011468 if ((ctxt == NULL) || (elemDecl == NULL) ||
11469 ((elemDecl != NULL) &&
11470 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011471 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011472 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011473
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011474 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011475 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011476
11477 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011478 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011479 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011480 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011481 elemDecl->namedTypeNs);
11482 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011483 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011484 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011485 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011486 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011487 XML_SCHEMA_TYPE_BASIC, "type definition");
11488 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011489 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011490 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011491 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011492 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011493
Daniel Veillardc0826a72004-08-10 14:17:33 +000011494 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011495 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011496 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011497 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011498 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11499 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011500 if (substHead == NULL) {
11501 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011502 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011503 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011504 "substitutionGroup", elemDecl->substGroup,
11505 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011506 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011507 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011508 /*
11509 * Set the "substitution group affiliation".
11510 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011511 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011512 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011513 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011514 * (type definition)...otherwise the {type definition} of the
11515 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011516 * the substitutionGroup [attribute], if present
11517 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011518 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011519 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011520 }
11521 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011522 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11523 (elemDecl->substGroup == NULL))
11524 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011525}
11526
11527/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011528 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011529 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011530 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011531 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011532 * Checks and builds the "member type definitions" property of the union
11533 * simple type. This handles part (1), part (2) is done in
11534 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11535 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011536 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011537 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011538static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011539xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11540 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011541{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011542
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011543 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011544 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011545
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011546 /*
11547 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11548 * define the explicit members as the type definitions ·resolved·
11549 * to by the items in the ·actual value· of the memberTypes [attribute],
11550 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011551 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011552 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011553 /*
11554 * Resolve references.
11555 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011556 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011557 lastLink = NULL;
11558 while (link != NULL) {
11559 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011560
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011561 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11562 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11563
11564 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11565 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11566 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011567 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011568 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11569 /*
11570 * Remove the member type link.
11571 */
11572 if (lastLink == NULL)
11573 type->memberTypes = link->next;
11574 else
11575 lastLink->next = link->next;
11576 newLink = link;
11577 link = link->next;
11578 xmlFree(newLink);
11579 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011580 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011581 lastLink = link;
11582 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011583 }
11584 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011585 /*
11586 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011587 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011588 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011589 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011590 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11591 if (link == NULL) {
11592 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11593 return (-1);
11594 }
11595 link->type = memberType;
11596 link->next = NULL;
11597 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011598 type->memberTypes = link;
11599 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011600 lastLink->next = link;
11601 lastLink = link;
11602 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011603 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011604 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011605}
11606
Daniel Veillard4255d502002-04-16 15:50:10 +000011607/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011608 * xmlSchemaIsDerivedFromBuiltInType:
11609 * @ctxt: the schema parser context
11610 * @type: the type definition
11611 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011612 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011613 *
11614 * Returns 1 if the type has the given value type, or
11615 * is derived from such a type.
11616 */
William M. Brack803812b2004-06-03 02:11:24 +000011617static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011618xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011619{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011620 if (type == NULL)
11621 return (0);
11622 if (IS_COMPLEX_TYPE(type))
11623 return (0);
11624 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11625 if (type->builtInType == valType)
11626 return(1);
11627 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11628 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11629 return (0);
11630 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11631 } else
11632 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011633
11634 return (0);
11635}
11636
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011637#if 0
11638/**
11639 * xmlSchemaIsDerivedFromBuiltInType:
11640 * @ctxt: the schema parser context
11641 * @type: the type definition
11642 * @valType: the value type
11643 *
11644 *
11645 * Returns 1 if the type has the given value type, or
11646 * is derived from such a type.
11647 */
11648static int
11649xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11650{
11651 if (type == NULL)
11652 return (0);
11653 if (IS_COMPLEX_TYPE(type))
11654 return (0);
11655 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11656 if (type->builtInType == valType)
11657 return(1);
11658 return (0);
11659 } else
11660 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11661
11662 return (0);
11663}
11664#endif
11665
11666static xmlSchemaTypePtr
11667xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11668{
11669 if (type == NULL)
11670 return (NULL);
11671 if (IS_COMPLEX_TYPE(type))
11672 return (NULL);
11673 if (type->type == XML_SCHEMA_TYPE_BASIC)
11674 return(type);
11675 else
11676 return(xmlSchemaQueryBuiltInType(type->subtypes));
11677
11678 return (NULL);
11679}
11680
Daniel Veillard3646d642004-06-02 19:19:14 +000011681/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011682 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011683 * @type: the simpleType definition
11684 *
11685 * Returns the primitive type of the given type or
11686 * NULL in case of error.
11687 */
11688static xmlSchemaTypePtr
11689xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11690{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011691
Daniel Veillard01fa6152004-06-29 17:04:39 +000011692 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011693 /*
11694 * Note that anySimpleType is actually not a primitive type
11695 * but we need that here.
11696 */
11697 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11698 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011699 return (type);
11700 type = type->baseType;
11701 }
11702
11703 return (NULL);
11704}
11705
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011706#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011707/**
11708 * xmlSchemaGetBuiltInTypeAncestor:
11709 * @type: the simpleType definition
11710 *
11711 * Returns the primitive type of the given type or
11712 * NULL in case of error.
11713 */
11714static xmlSchemaTypePtr
11715xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11716{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011717 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011718 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011719 while (type != NULL) {
11720 if (type->type == XML_SCHEMA_TYPE_BASIC)
11721 return (type);
11722 type = type->baseType;
11723 }
11724
11725 return (NULL);
11726}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011727#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011728
Daniel Veillard01fa6152004-06-29 17:04:39 +000011729/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011730 * xmlSchemaBuildAttributeUsesOwned:
11731 * @ctxt: the schema parser context
11732 * @type: the complex type definition
11733 * @cur: the attribute declaration list
11734 * @lastUse: the top of the attribute use list
11735 *
11736 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011737 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011738 * xmlSchemaBuildAttributeValidation only.
11739 */
11740static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011741xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011742 xmlSchemaAttributePtr cur,
11743 xmlSchemaAttributeLinkPtr *uses,
11744 xmlSchemaAttributeLinkPtr *lastUse)
11745{
11746 xmlSchemaAttributeLinkPtr tmp;
11747 while (cur != NULL) {
11748 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011749 /*
11750 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11751 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011752 * <attributeGroup> [children], if any."
11753 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011754 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11755 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011756 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011757 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011758 }
11759 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011760 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011761 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011762 */
11763 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011764 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11765 if (tmp == NULL) {
11766 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11767 return (-1);
11768 }
11769 tmp->attr = cur;
11770 tmp->next = NULL;
11771 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011772 *uses = tmp;
11773 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011774 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011775 *lastUse = tmp;
11776 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011777 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011778 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011779 return (0);
11780}
11781
Daniel Veillard50355f02004-06-08 17:52:16 +000011782/**
11783 * xmlSchemaCloneWildcardNsConstraints:
11784 * @ctxt: the schema parser context
11785 * @dest: the destination wildcard
11786 * @source: the source wildcard
11787 *
11788 * Clones the namespace constraints of source
11789 * and assignes them to dest.
11790 * Returns -1 on internal error, 0 otherwise.
11791 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011792static int
11793xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11794 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011795 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011796{
11797 xmlSchemaWildcardNsPtr cur, tmp, last;
11798
11799 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011800 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011801 (*dest)->any = source->any;
11802 cur = source->nsSet;
11803 last = NULL;
11804 while (cur != NULL) {
11805 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11806 if (tmp == NULL)
11807 return(-1);
11808 tmp->value = cur->value;
11809 if (last == NULL)
11810 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011811 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011812 last->next = tmp;
11813 last = tmp;
11814 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011815 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011816 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011817 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011818 if (source->negNsSet != NULL) {
11819 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11820 if ((*dest)->negNsSet == NULL)
11821 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011822 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011823 } else
11824 (*dest)->negNsSet = NULL;
11825 return(0);
11826}
11827
Daniel Veillard50355f02004-06-08 17:52:16 +000011828/**
11829 * xmlSchemaUnionWildcards:
11830 * @ctxt: the schema parser context
11831 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011832 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011833 *
11834 * Unions the namespace constraints of the given wildcards.
11835 * @completeWild will hold the resulting union.
11836 * Returns a positive error code on failure, -1 in case of an
11837 * internal error, 0 otherwise.
11838 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011839static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011840xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011841 xmlSchemaWildcardPtr completeWild,
11842 xmlSchemaWildcardPtr curWild)
11843{
11844 xmlSchemaWildcardNsPtr cur, curB, tmp;
11845
11846 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011847 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011848 * value.
11849 */
11850 if ((completeWild->any == curWild->any) &&
11851 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11852 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011853
Daniel Veillard3646d642004-06-02 19:19:14 +000011854 if ((completeWild->negNsSet == NULL) ||
11855 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011856
Daniel Veillard3646d642004-06-02 19:19:14 +000011857 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011858 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011859
11860 /*
11861 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011862 */
11863 cur = completeWild->nsSet;
11864 while (cur != NULL) {
11865 found = 0;
11866 curB = curWild->nsSet;
11867 while (curB != NULL) {
11868 if (cur->value == curB->value) {
11869 found = 1;
11870 break;
11871 }
11872 curB = curB->next;
11873 }
11874 if (!found)
11875 break;
11876 cur = cur->next;
11877 }
11878 if (found)
11879 return(0);
11880 } else
11881 return(0);
11882 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011883 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011884 /*
11885 * 2 If either O1 or O2 is any, then any must be the value
11886 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011887 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011888 if (completeWild->any == 0) {
11889 completeWild->any = 1;
11890 if (completeWild->nsSet != NULL) {
11891 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11892 completeWild->nsSet = NULL;
11893 }
11894 if (completeWild->negNsSet != NULL) {
11895 xmlFree(completeWild->negNsSet);
11896 completeWild->negNsSet = NULL;
11897 }
11898 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011899 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011900 }
11901 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011902 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011903 * then the union of those sets must be the value.
11904 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011905 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011906 int found;
11907 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011908
Daniel Veillard3646d642004-06-02 19:19:14 +000011909 cur = curWild->nsSet;
11910 start = completeWild->nsSet;
11911 while (cur != NULL) {
11912 found = 0;
11913 curB = start;
11914 while (curB != NULL) {
11915 if (cur->value == curB->value) {
11916 found = 1;
11917 break;
11918 }
11919 curB = curB->next;
11920 }
11921 if (!found) {
11922 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011923 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011924 return (-1);
11925 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011926 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011927 completeWild->nsSet = tmp;
11928 }
11929 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011930 }
11931
Daniel Veillard3646d642004-06-02 19:19:14 +000011932 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011933 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011934 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011935 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011936 * or ·absent·), then a pair of not and ·absent· must be the value.
11937 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011938 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011939 (curWild->negNsSet != NULL) &&
11940 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11941 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011942
11943 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011944 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011945 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011946 * 5.
11947 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011948 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011949 (completeWild->negNsSet->value != NULL) &&
11950 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011951 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011952 (curWild->negNsSet->value != NULL) &&
11953 (completeWild->nsSet != NULL))) {
11954
11955 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011956
Daniel Veillard3646d642004-06-02 19:19:14 +000011957 if (completeWild->nsSet != NULL) {
11958 cur = completeWild->nsSet;
11959 curB = curWild->negNsSet;
11960 } else {
11961 cur = curWild->nsSet;
11962 curB = completeWild->negNsSet;
11963 }
11964 nsFound = 0;
11965 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011966 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011967 absentFound = 1;
11968 else if (cur->value == curB->value)
11969 nsFound = 1;
11970 if (nsFound && absentFound)
11971 break;
11972 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011973 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011974
11975 if (nsFound && absentFound) {
11976 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011977 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011978 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011979 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011980 completeWild->any = 1;
11981 if (completeWild->nsSet != NULL) {
11982 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11983 completeWild->nsSet = NULL;
11984 }
11985 if (completeWild->negNsSet != NULL) {
11986 xmlFree(completeWild->negNsSet);
11987 completeWild->negNsSet = NULL;
11988 }
11989 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011990 /*
11991 * 5.2 If the set S includes the negated namespace name
11992 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000011993 * be the value.
11994 */
11995 if (completeWild->nsSet != NULL) {
11996 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11997 completeWild->nsSet = NULL;
11998 }
11999 if (completeWild->negNsSet == NULL) {
12000 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12001 if (completeWild->negNsSet == NULL)
12002 return (-1);
12003 }
12004 completeWild->negNsSet->value = NULL;
12005 } else if ((!nsFound) && absentFound) {
12006 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012007 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012008 * namespace name, then the union is not expressible.
12009 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012010 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012011 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012012 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012013 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012014 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012015 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012016 /*
12017 * 5.4 If the set S does not include either the negated namespace
12018 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012019 * and a namespace name must be the value.
12020 */
12021 if (completeWild->negNsSet == NULL) {
12022 if (completeWild->nsSet != NULL) {
12023 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12024 completeWild->nsSet = NULL;
12025 }
12026 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12027 if (completeWild->negNsSet == NULL)
12028 return (-1);
12029 completeWild->negNsSet->value = curWild->negNsSet->value;
12030 }
12031 }
12032 return (0);
12033 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012034 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012035 * 6.
12036 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012037 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012038 (completeWild->negNsSet->value == NULL) &&
12039 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012040 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012041 (curWild->negNsSet->value == NULL) &&
12042 (completeWild->nsSet != NULL))) {
12043
12044 if (completeWild->nsSet != NULL) {
12045 cur = completeWild->nsSet;
12046 } else {
12047 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012048 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012049 while (cur != NULL) {
12050 if (cur->value == NULL) {
12051 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012052 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012053 * value.
12054 */
12055 completeWild->any = 1;
12056 if (completeWild->nsSet != NULL) {
12057 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12058 completeWild->nsSet = NULL;
12059 }
12060 if (completeWild->negNsSet != NULL) {
12061 xmlFree(completeWild->negNsSet);
12062 completeWild->negNsSet = NULL;
12063 }
12064 return (0);
12065 }
12066 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012067 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012068 if (completeWild->negNsSet == NULL) {
12069 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012070 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012071 * and ·absent· must be the value.
12072 */
12073 if (completeWild->nsSet != NULL) {
12074 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12075 completeWild->nsSet = NULL;
12076 }
12077 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12078 if (completeWild->negNsSet == NULL)
12079 return (-1);
12080 completeWild->negNsSet->value = NULL;
12081 }
12082 return (0);
12083 }
12084 return (0);
12085
12086}
12087
Daniel Veillard50355f02004-06-08 17:52:16 +000012088/**
12089 * xmlSchemaIntersectWildcards:
12090 * @ctxt: the schema parser context
12091 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012092 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012093 *
12094 * Intersects the namespace constraints of the given wildcards.
12095 * @completeWild will hold the resulting intersection.
12096 * Returns a positive error code on failure, -1 in case of an
12097 * internal error, 0 otherwise.
12098 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012099static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012100xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012101 xmlSchemaWildcardPtr completeWild,
12102 xmlSchemaWildcardPtr curWild)
12103{
William M. Brack803812b2004-06-03 02:11:24 +000012104 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012105
12106 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012107 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012108 * value.
12109 */
12110 if ((completeWild->any == curWild->any) &&
12111 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12112 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012113
Daniel Veillard3646d642004-06-02 19:19:14 +000012114 if ((completeWild->negNsSet == NULL) ||
12115 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012116
Daniel Veillard3646d642004-06-02 19:19:14 +000012117 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012118 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012119
12120 /*
12121 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012122 */
12123 cur = completeWild->nsSet;
12124 while (cur != NULL) {
12125 found = 0;
12126 curB = curWild->nsSet;
12127 while (curB != NULL) {
12128 if (cur->value == curB->value) {
12129 found = 1;
12130 break;
12131 }
12132 curB = curB->next;
12133 }
12134 if (!found)
12135 break;
12136 cur = cur->next;
12137 }
12138 if (found)
12139 return(0);
12140 } else
12141 return(0);
12142 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012143 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012144 /*
12145 * 2 If either O1 or O2 is any, then the other must be the value.
12146 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012147 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012148 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012149 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012150 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012151 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012152 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012153 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12154 * name or ·absent·) and the other is a set of (namespace names or
12155 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012156 * the set, minus ·absent· if it was in the set, must be the value.
12157 */
12158 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12159 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12160 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012161
Daniel Veillard3646d642004-06-02 19:19:14 +000012162 if (completeWild->nsSet == NULL) {
12163 neg = completeWild->negNsSet->value;
12164 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12165 return(-1);
12166 } else
12167 neg = curWild->negNsSet->value;
12168 /*
12169 * Remove absent and negated.
12170 */
12171 prev = NULL;
12172 cur = completeWild->nsSet;
12173 while (cur != NULL) {
12174 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012175 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012176 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012177 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012178 prev->next = cur->next;
12179 xmlFree(cur);
12180 break;
12181 }
12182 prev = cur;
12183 cur = cur->next;
12184 }
12185 if (neg != NULL) {
12186 prev = NULL;
12187 cur = completeWild->nsSet;
12188 while (cur != NULL) {
12189 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012190 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012191 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012192 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012193 prev->next = cur->next;
12194 xmlFree(cur);
12195 break;
12196 }
12197 prev = cur;
12198 cur = cur->next;
12199 }
12200 }
12201
12202 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012203 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012204 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012205 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012206 * then the intersection of those sets must be the value.
12207 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012208 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012209 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012210
Daniel Veillard3646d642004-06-02 19:19:14 +000012211 cur = completeWild->nsSet;
12212 prev = NULL;
12213 while (cur != NULL) {
12214 found = 0;
12215 curB = curWild->nsSet;
12216 while (curB != NULL) {
12217 if (cur->value == curB->value) {
12218 found = 1;
12219 break;
12220 }
12221 curB = curB->next;
12222 }
12223 if (!found) {
12224 if (prev == NULL)
12225 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012226 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012227 prev->next = cur->next;
12228 tmp = cur->next;
12229 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012230 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012231 continue;
12232 }
12233 prev = cur;
12234 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012235 }
12236
Daniel Veillard3646d642004-06-02 19:19:14 +000012237 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012238 }
12239 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012240 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012241 */
12242 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012243 (curWild->negNsSet != NULL) &&
12244 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012245 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012246 (curWild->negNsSet->value != NULL)) {
12247
12248 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012249 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012250 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012251 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012252 }
12253 /*
12254 * 6 If the one is a negation of a namespace name and the other
12255 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012256 * of a namespace name must be the value.
12257 */
12258 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12259 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012260 (completeWild->negNsSet->value == NULL)) {
12261 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012262 }
12263 return(0);
12264}
12265
Daniel Veillard50355f02004-06-08 17:52:16 +000012266/**
12267 * xmlSchemaIsWildcardNsConstraintSubset:
12268 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012269 * @sub: the first wildcard
12270 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012271 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012272 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12273 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012274 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012275 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012276 */
12277static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012278xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12279 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012280{
Daniel Veillard50355f02004-06-08 17:52:16 +000012281 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012282 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012283 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012284 if (super->any)
12285 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012286 /*
12287 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12288 * 2.2 super must be a pair of not and the same value.
12289 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012290 if ((sub->negNsSet != NULL) &&
12291 (super->negNsSet != NULL) &&
12292 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012293 return (0);
12294 /*
12295 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012296 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012297 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012298 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012299 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012300 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012301 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012302 xmlSchemaWildcardNsPtr cur, curB;
12303 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012304
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012305 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012306 while (cur != NULL) {
12307 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012308 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012309 while (curB != NULL) {
12310 if (cur->value == curB->value) {
12311 found = 1;
12312 break;
12313 }
12314 curB = curB->next;
12315 }
12316 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012317 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012318 cur = cur->next;
12319 }
12320 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012321 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012322 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012323 xmlSchemaWildcardNsPtr cur;
12324 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012325 * 3.2.2 super must be a pair of not and a namespace name or
12326 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012327 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012328 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012329 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012330 if (cur->value == super->negNsSet->value)
12331 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012332 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012333 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012334 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012335 }
12336 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012337 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012338}
12339
12340/**
12341 * xmlSchemaBuildCompleteAttributeWildcard:
12342 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012343 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012344 * @completeWild: the resulting complete wildcard
12345 *
12346 * Returns -1 in case of an internal error, 0 otherwise.
12347 */
12348static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012349xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012350 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012351 xmlSchemaWildcardPtr *completeWild)
12352{
Daniel Veillard3646d642004-06-02 19:19:14 +000012353 while (attrs != NULL) {
12354 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12355 xmlSchemaAttributeGroupPtr group;
12356
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012357 group = (xmlSchemaAttributeGroupPtr) attrs;
12358 /*
12359 * Handle attribute group references.
12360 */
12361 if (group->ref != NULL) {
12362 if (group->refItem == NULL) {
12363 /*
12364 * TODO: Should we raise a warning here?
12365 */
12366 /*
12367 * The referenced attribute group definition could not
12368 * be resolved beforehand, so skip.
12369 */
12370 attrs = attrs->next;
12371 continue;
12372 } else
12373 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012374 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012375 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012376 * For every attribute group definition, an intersected wildcard
12377 * will be created (assumed that a wildcard exists on the
12378 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012379 * at all).
12380 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12381 * that the intersection will be performed only once.
12382 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012383 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12384 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012385 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012386 group->attributes, &group->attributeWildcard) == -1)
12387 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012388 }
12389 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012390 }
12391 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012392 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012393 /*
12394 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012395 *
12396 * Although the complete wildcard might not correspond to any
12397 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012398 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012399 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12400 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12401 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012402 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012403 completeWild, group->attributeWildcard) == -1)
12404 return (-1);
12405 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012406 (*completeWild)->node = group->attributeWildcard->node;
12407 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012408 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012409 }
12410 }
12411 attrs = attrs->next;
12412 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012413
12414 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012415}
12416
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012417static int
12418xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12419 int *fixed,
12420 const xmlChar **value,
12421 xmlSchemaValPtr *val)
12422{
12423 *fixed = 0;
12424 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012425 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012426 *val = NULL;
12427
12428 if (item->defValue == NULL)
12429 item = item->refDecl;
12430
12431 if (item == NULL)
12432 return (0);
12433
12434 if (item->defValue != NULL) {
12435 *value = item->defValue;
12436 if (val != 0)
12437 *val = item->defVal;
12438 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12439 *fixed = 1;
12440 return (1);
12441 }
12442 return (0);
12443}
Daniel Veillard3646d642004-06-02 19:19:14 +000012444/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012445 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012446 * @wild: the wildcard
12447 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012448 *
12449 * Validation Rule: Wildcard allows Namespace Name
12450 * (cvc-wildcard-namespace)
12451 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012452 *
12453 * Returns 1 if the given namespace matches the wildcard,
12454 * 0 otherwise.
12455 */
12456static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012457xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12458 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012459{
12460 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012461 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012462
12463 if (wild->any)
12464 return(1);
12465 else if (wild->nsSet != NULL) {
12466 xmlSchemaWildcardNsPtr cur;
12467
12468 cur = wild->nsSet;
12469 while (cur != NULL) {
12470 if (xmlStrEqual(cur->value, ns))
12471 return(1);
12472 cur = cur->next;
12473 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012474 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012475 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012476 return(1);
12477
Daniel Veillard3646d642004-06-02 19:19:14 +000012478 return(0);
12479}
12480
12481/**
12482 * xmlSchemaBuildAttributeValidation:
12483 * @ctxt: the schema parser context
12484 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012485 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012486 *
12487 * Builds the wildcard and the attribute uses on the given complex type.
12488 * Returns -1 if an internal error occurs, 0 otherwise.
12489 */
12490static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012491xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12492 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012493{
12494 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012495 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12496 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012497 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012498 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012499 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012500 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012501
Daniel Veillard01fa6152004-06-29 17:04:39 +000012502 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012503 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012504 * Complex Type Definition with complex content Schema Component.
12505 *
12506 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012507 * TODO: Add checks for absent referenced attribute declarations and
12508 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012509 */
12510 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012511 PERROR_INT("xmlSchemaBuildAttributeValidation",
12512 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012513 return (-1);
12514 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012515 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012516 PERROR_INT("xmlSchemaBuildAttributeValidation",
12517 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012518 return (-1);
12519 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012520 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012521 /*
12522 * Inherit the attribute uses of the base type.
12523 */
12524 /*
12525 * NOTE: It is allowed to "extend" the anyType complex type.
12526 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012527 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012528 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012529 for (cur = baseType->attributeUses; cur != NULL;
12530 cur = cur->next) {
12531 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012532 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12533 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012534 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012535 "building attribute uses of complexType", NULL);
12536 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012537 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012538 tmp->attr = cur->attr;
12539 tmp->next = NULL;
12540 if (type->attributeUses == NULL) {
12541 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012542 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012543 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012544 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012545 }
12546 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012547 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012548 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012549 /*
12550 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012551 */
12552 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12553 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012554 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012555 * NOTE: During the parse time, the wildcard is created on the complexType
12556 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012557 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012558 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012559 PERROR_INT("xmlSchemaBuildAttributeValidation",
12560 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012561 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012562 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012563
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012564 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12565 ((IS_ANYTYPE(baseType)) ||
12566 ((baseType != NULL) &&
12567 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12568 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012569 if (type->attributeWildcard != NULL) {
12570 /*
12571 * Union the complete wildcard with the base wildcard.
12572 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012573 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012574 baseType->attributeWildcard) == -1)
12575 return (-1);
12576 } else {
12577 /*
12578 * Just inherit the wildcard.
12579 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012580 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012581 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012582 * wildcard is shared.
12583 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012584 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012585 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012586 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012587
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012588 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12589 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012590 /*
12591 * Derivation Valid (Restriction, Complex)
12592 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012593 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012594 if (baseType->attributeWildcard == NULL) {
12595 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012596 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012597 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012598 "The type has an attribute wildcard, "
12599 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012600 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012601 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012602 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012603 } else if (xmlSchemaCheckCOSNSSubset(
12604 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012605 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012606 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012607 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012608 NULL, type, NULL,
12609 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012610 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012611 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12612 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012613 return (1);
12614 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012615 /* 4.3 Unless the {base type definition} is the ·ur-type
12616 * definition·, the complex type definition's {attribute
12617 * wildcard}'s {process contents} must be identical to or
12618 * stronger than the {base type definition}'s {attribute
12619 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012620 * than lax is stronger than skip.
12621 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012622 if ((! IS_ANYTYPE(baseType)) &&
12623 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012624 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012625 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012626 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012627 NULL, type, NULL,
12628 "The 'process contents' of the attribute wildcard is "
12629 "weaker than the one in the base type %s",
12630 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012631 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012632 return (1);
12633 }
12634 }
12635 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12636 /*
12637 * Derivation Valid (Extension)
12638 * At this point the type and the base have both, either
12639 * no wildcard or a wildcard.
12640 */
12641 if ((baseType->attributeWildcard != NULL) &&
12642 (baseType->attributeWildcard != type->attributeWildcard)) {
12643 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012644 if (xmlSchemaCheckCOSNSSubset(
12645 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012646 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012647 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012648 NULL, type, NULL,
12649 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012650 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012651 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12652 FREE_AND_NULL(str)
12653 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012654 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012655 }
12656 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012657
Daniel Veillard3646d642004-06-02 19:19:14 +000012658 /*
12659 * Gather attribute uses defined by this type.
12660 */
12661 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012662 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012663 &uses, &lastUse) == -1) {
12664 return (-1);
12665 }
12666 }
12667 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012668 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012669 * not have identical {name}s and {target namespace}s."
12670 *
12671 * For "extension" this is done further down.
12672 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012673 if ((uses != NULL) && ((type->flags &
12674 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012675 cur = uses;
12676 while (cur != NULL) {
12677 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012678 while (tmp != NULL) {
12679 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012680 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012681 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012682 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12683
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012684 xmlSchemaPAttrUseErr(pctxt,
12685 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12686 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012687 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012688 xmlSchemaFormatQName(&str,
12689 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12690 xmlSchemaGetAttrName(tmp->attr)));
12691 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012692 break;
12693 }
12694 tmp = tmp->next;
12695 }
12696 cur = cur->next;
12697 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012698 }
12699 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012700 /*
12701 * Derive by restriction.
12702 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012703 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012704 type->attributeUses = uses;
12705 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012706 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012707 const xmlChar *bEffValue;
12708 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012709
12710 cur = uses;
12711 while (cur != NULL) {
12712 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012713 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012714 base = type->attributeUses;
12715 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012716 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012717 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012718 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012719 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012720
12721 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012722
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012723 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012724 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12725 (base->attr->occurs ==
12726 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12727 /*
12728 * NOOP.
12729 */
12730 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012731 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12732 (base->attr->occurs ==
12733 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012734 /*
12735 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012736 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012737 xmlSchemaPAttrUseErr(pctxt,
12738 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12739 type, cur->attr,
12740 "The 'optional' use is inconsistent with a "
12741 "matching 'required' use of the base type",
12742 NULL);
12743 } else if ((cur->attr->occurs ==
12744 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12745 (base->attr->occurs ==
12746 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12747 /*
12748 * derivation-ok-restriction 3
12749 */
12750 xmlSchemaPCustomErr(pctxt,
12751 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12752 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012753 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012754 "attribute use '%s' of the base type is "
12755 "missing",
12756 xmlSchemaFormatQName(&str,
12757 xmlSchemaGetAttrTargetNsURI(base->attr),
12758 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012759 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012760 } else if (xmlSchemaCheckCOSSTDerivedOK(
12761 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12762
12763 /*
12764 * SPEC (2.1.2) "R's {attribute declaration}'s
12765 * {type definition} must be validly derived from
12766 * B's {type definition} given the empty set as
12767 * defined in Type Derivation OK (Simple) (§3.14.6)."
12768 */
12769 xmlSchemaPAttrUseErr(pctxt,
12770 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12771 type, cur->attr,
12772 "The attribute declaration's type "
12773 "definition is not validly derived from "
12774 "the corresponding definition in the "
12775 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012776 } else {
12777 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012778 * 2.1.3 [Definition:] Let the effective value
12779 * constraint of an attribute use be its {value
12780 * constraint}, if present, otherwise its {attribute
12781 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012782 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012783 xmlSchemaGetEffectiveValueConstraint(base->attr,
12784 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012785 /*
12786 * 2.1.3 ... one of the following must be true
12787 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012788 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012789 * ·absent· or default.
12790 */
12791 if ((bEffValue != NULL) &&
12792 (effFixed == 1)) {
12793 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012794
12795 xmlSchemaGetEffectiveValueConstraint(base->attr,
12796 &effFixed, &rEffValue, 0);
12797 /*
12798 * 2.1.3.2 R's ·effective value constraint· is
12799 * fixed with the same string as B's.
12800 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012801 */
12802 if ((effFixed == 0) ||
12803 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012804 xmlSchemaPAttrUseErr(pctxt,
12805 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12806 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012807 "The effective value constraint of the "
12808 "attribute use is inconsistent with "
12809 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012810 NULL);
12811 } else {
12812 /*
12813 * Override the attribute use.
12814 */
12815 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012816 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012817 } else
12818 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012819 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012820
Daniel Veillard3646d642004-06-02 19:19:14 +000012821 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012822 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012823 base = base->next;
12824 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012825
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012826 if ((!found) && (cur->attr->occurs !=
12827 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12828 /*
12829 * derivation-ok-restriction 2.2
12830 */
12831 if ((baseType->attributeWildcard == NULL) ||
12832 (xmlSchemaCheckCVCWildcardNamespace(
12833 baseType->attributeWildcard,
12834 cur->attr->targetNamespace) != 1)) {
12835 xmlSchemaPAttrUseErr(pctxt,
12836 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12837 type, cur->attr,
12838 "Neither a matching attribute use, "
12839 "nor a matching wildcard in the base type does exist",
12840 NULL);
12841 } else {
12842 /*
12843 * Add the attribute use.
12844 *
12845 * Note that this may lead to funny derivation error reports, if
12846 * multiple equal attribute uses exist; but this is not
12847 * allowed anyway, and it will be reported beforehand.
12848 */
12849 tmp = cur;
12850 if (prev != NULL)
12851 prev->next = cur->next;
12852 else
12853 uses = cur->next;
12854 cur = cur->next;
12855 tmp->next = NULL;
12856 if (type->attributeUses == NULL) {
12857 type->attributeUses = tmp;
12858 } else
12859 lastBaseUse->next = tmp;
12860 lastBaseUse = tmp;
12861
12862 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012863 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012864 }
12865 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012866 cur = cur->next;
12867 }
12868 if (uses != NULL)
12869 xmlSchemaFreeAttributeUseList(uses);
12870 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012871 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012872 /*
12873 * The spec allows only appending, and not other kinds of extensions.
12874 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012875 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012876 */
12877 if (uses != NULL) {
12878 if (type->attributeUses == NULL) {
12879 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012880 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012881 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012882 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012883 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012884 PERROR_INT("xmlSchemaBuildAttributeValidation",
12885 "no derivation method");
12886 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012887 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012888 /*
12889 * 3.4.6 -> Complex Type Definition Properties Correct
12890 */
12891 if (type->attributeUses != NULL) {
12892 cur = type->attributeUses;
12893 prev = NULL;
12894 while (cur != NULL) {
12895 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012896 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012897 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012898 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012899 * Note that this was already done for "restriction" and types derived from
12900 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012901 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012902 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12903 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012904 while (tmp != NULL) {
12905 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012906 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012907 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012908 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012909
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012910 xmlSchemaPAttrUseErr(pctxt,
12911 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12912 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012913 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012914 break;
12915 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012916 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012917 }
12918 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012919 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012920 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012921 * not have {type definition}s which are or are derived from ID.
12922 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012923 if ((cur->attr->subtypes != NULL) &&
12924 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12925 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012926 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012927 xmlSchemaPAttrUseErr(pctxt,
12928 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12929 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012930 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012931 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012932 NULL);
12933 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012934 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012935 id = cur;
12936 }
12937 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012938 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012939 * stage is to be able to catch dublicate attribute uses. So we had to keep
12940 * prohibited uses in the list as well.
12941 */
12942 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12943 tmp = cur;
12944 if (prev == NULL)
12945 type->attributeUses = cur->next;
12946 else
12947 prev->next = cur->next;
12948 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012949 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012950 } else {
12951 prev = cur;
12952 cur = cur->next;
12953 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012954 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012955 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012956 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012957 * TODO: This check should be removed if we are 100% sure of
12958 * the base type attribute uses already being built.
12959 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012960 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012961 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012962 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012963 PERROR_INT("xmlSchemaBuildAttributeValidation",
12964 "attribute uses not builded on base type");
12965 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012966 return (0);
12967}
12968
12969/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012970 * xmlSchemaTypeFinalContains:
12971 * @schema: the schema
12972 * @type: the type definition
12973 * @final: the final
12974 *
12975 * Evaluates if a type definition contains the given "final".
12976 * This does take "finalDefault" into account as well.
12977 *
12978 * Returns 1 if the type does containt the given "final",
12979 * 0 otherwise.
12980 */
12981static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012982xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012983{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012984 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012985 return (0);
12986 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012987 return (1);
12988 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012989 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012990}
12991
12992/**
12993 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12994 * @type: the Union Simple Type
12995 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012996 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012997 * returns NULL otherwise.
12998 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012999static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013000xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13001{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013002 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013003 if (type->memberTypes != NULL)
13004 return (type->memberTypes);
13005 else
13006 type = type->baseType;
13007 }
13008 return (NULL);
13009}
13010
13011/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013012 * xmlSchemaGetParticleTotalRangeMin:
13013 * @particle: the particle
13014 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013015 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013016 * (all and sequence) + (choice)
13017 *
13018 * Returns the minimun Effective Total Range.
13019 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013020static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013021xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013022{
13023 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013024 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013025 return (0);
13026 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013027 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013028 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013029 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013030
13031 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013032 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013033 while (part != NULL) {
13034 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13035 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013036 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013037 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013038 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013039 if (cur == 0)
13040 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013041 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013042 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013043 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013044 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013045 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013046 } else {
13047 /* <all> and <sequence> */
13048 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013049 xmlSchemaParticlePtr part =
13050 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013051
13052 if (part == NULL)
13053 return (0);
13054 do {
13055 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13056 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013057 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013058 else
13059 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013060 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013061 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013062 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013063 }
13064}
13065
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013066/**
13067 * xmlSchemaGetParticleTotalRangeMax:
13068 * @particle: the particle
13069 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013070 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013071 * (all and sequence) + (choice)
13072 *
13073 * Returns the maximum Effective Total Range.
13074 */
13075static int
13076xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13077{
13078 if ((particle->children == NULL) ||
13079 (particle->children->children == NULL))
13080 return (0);
13081 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13082 int max = -1, cur;
13083 xmlSchemaParticlePtr part =
13084 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013085
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013086 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13087 if (part->children == NULL)
13088 continue;
13089 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13090 (part->children->type == XML_SCHEMA_TYPE_ANY))
13091 cur = part->maxOccurs;
13092 else
13093 cur = xmlSchemaGetParticleTotalRangeMax(part);
13094 if (cur == UNBOUNDED)
13095 return (UNBOUNDED);
13096 if ((max < cur) || (max == -1))
13097 max = cur;
13098 }
13099 /* TODO: Handle overflows? */
13100 return (particle->maxOccurs * max);
13101 } else {
13102 /* <all> and <sequence> */
13103 int sum = 0, cur;
13104 xmlSchemaParticlePtr part =
13105 (xmlSchemaParticlePtr) particle->children->children;
13106
13107 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13108 if (part->children == NULL)
13109 continue;
13110 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13111 (part->children->type == XML_SCHEMA_TYPE_ANY))
13112 cur = part->maxOccurs;
13113 else
13114 cur = xmlSchemaGetParticleTotalRangeMax(part);
13115 if (cur == UNBOUNDED)
13116 return (UNBOUNDED);
13117 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13118 return (UNBOUNDED);
13119 sum += cur;
13120 }
13121 /* TODO: Handle overflows? */
13122 return (particle->maxOccurs * sum);
13123 }
13124}
13125
13126/**
13127 * xmlSchemaIsParticleEmptiable:
13128 * @particle: the particle
13129 *
13130 * Schema Component Constraint: Particle Emptiable
13131 * Checks whether the given particle is emptiable.
13132 *
13133 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013134 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013135static int
13136xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13137{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013138 /*
13139 * SPEC (1) "Its {min occurs} is 0."
13140 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013141 if ((particle == NULL) || (particle->minOccurs == 0) ||
13142 (particle->children == NULL))
13143 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013144 /*
13145 * SPEC (2) "Its {term} is a group and the minimum part of the
13146 * effective total range of that group, [...] is 0."
13147 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013148 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013149 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013150 return (1);
13151 }
13152 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013153}
13154
13155/**
13156 * xmlSchemaCheckCOSSTDerivedOK:
13157 * @type: the derived simple type definition
13158 * @baseType: the base type definition
13159 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013160 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013161 * Type Derivation OK (Simple) (cos-st-derived-OK)
13162 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013163 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013164 * derived from @baseType.
13165 *
13166 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013167 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013168static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013169xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13170 xmlSchemaTypePtr baseType,
13171 int subset)
13172{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013173 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013174 * 1 They are the same type definition.
13175 * TODO: The identy check might have to be more complex than this.
13176 */
13177 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013178 return (0);
13179 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013180 * 2.1 restriction is not in the subset, or in the {final}
13181 * of its own {base type definition};
13182 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013183 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013184 (xmlSchemaTypeFinalContains(type->baseType,
13185 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13186 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013187 }
13188 /* 2.2 */
13189 if (type->baseType == baseType) {
13190 /*
13191 * 2.2.1 D's ·base type definition· is B.
13192 */
13193 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013194 }
13195 /*
13196 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13197 * and is validly derived from B given the subset, as defined by this
13198 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013199 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013200 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013201 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013202 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013203 return (0);
13204 }
13205 /*
13206 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013207 * definition·.
13208 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013209 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013210 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013211 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013212 }
13213 /*
13214 * 2.2.4 B's {variety} is union and D is validly derived from a type
13215 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013216 * defined by this constraint.
13217 *
13218 * NOTE: This seems not to involve built-in types, since there is no
13219 * built-in Union Simple Type.
13220 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013221 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013222 xmlSchemaTypeLinkPtr cur;
13223
13224 cur = baseType->memberTypes;
13225 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013226 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013227 return (0);
13228 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013229 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013230 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013231
Daniel Veillard01fa6152004-06-29 17:04:39 +000013232 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13233}
13234
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013235/**
13236 * xmlSchemaCheckTypeDefCircularInternal:
13237 * @pctxt: the schema parser context
13238 * @ctxtType: the type definition
13239 * @ancestor: an ancestor of @ctxtType
13240 *
13241 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013242 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013243 *
13244 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13245 * circular, 0 otherwise.
13246 */
13247static int
13248xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13249 xmlSchemaTypePtr ctxtType,
13250 xmlSchemaTypePtr ancestor)
13251{
13252 int ret;
13253
13254 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13255 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013256
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013257 if (ctxtType == ancestor) {
13258 xmlSchemaPCustomErr(pctxt,
13259 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13260 NULL, ctxtType, GET_NODE(ctxtType),
13261 "The definition is circular", NULL);
13262 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13263 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013264 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13265 /*
13266 * Avoid inifinite recursion on circular types not yet checked.
13267 */
13268 return (0);
13269 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013270 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13271 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13272 ancestor->baseType);
13273 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13274 return (ret);
13275}
13276
13277/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013278 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013279 * @item: the complex/simple type definition
13280 * @ctxt: the parser context
13281 * @name: the name
13282 *
13283 * Checks for circular type definitions.
13284 */
13285static void
13286xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013287 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013288 const xmlChar * name ATTRIBUTE_UNUSED)
13289{
13290 if ((item == NULL) ||
13291 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13292 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13293 return;
13294 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13295
13296}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013297
13298/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013299 * xmlSchemaResolveTypeDefs:
13300 * @item: the complex/simple type definition
13301 * @ctxt: the parser context
13302 * @name: the name
13303 *
13304 * Checks for circular type definitions.
13305 */
13306static void
13307xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013308 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013309 const xmlChar * name ATTRIBUTE_UNUSED)
13310{
13311 if (typeDef == NULL)
13312 return;
13313
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013314 /*
13315 * Resolve the base type.
13316 */
13317 if (typeDef->baseType == NULL) {
13318 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13319 typeDef->base, typeDef->baseNs);
13320 if (typeDef->baseType == NULL) {
13321 xmlSchemaPResCompAttrErr(ctxt,
13322 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013323 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013324 "base", typeDef->base, typeDef->baseNs,
13325 XML_SCHEMA_TYPE_SIMPLE, NULL);
13326 return;
13327 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013328 }
13329 if (IS_SIMPLE_TYPE(typeDef)) {
13330 if (VARIETY_UNION(typeDef)) {
13331 /*
13332 * Resolve the memberTypes.
13333 */
13334 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13335 return;
13336 } else if (VARIETY_LIST(typeDef)) {
13337 /*
13338 * Resolve the itemType.
13339 */
13340 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13341 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13342 typeDef->ref, typeDef->refNs);
13343 if ((typeDef->subtypes == NULL) ||
13344 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13345 typeDef->subtypes = NULL;
13346 xmlSchemaPResCompAttrErr(ctxt,
13347 XML_SCHEMAP_SRC_RESOLVE,
13348 typeDef, typeDef->node,
13349 "itemType", typeDef->ref, typeDef->refNs,
13350 XML_SCHEMA_TYPE_SIMPLE, NULL);
13351 }
13352 }
13353 return;
13354 }
13355 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013356}
13357
13358
13359
13360/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013361 * xmlSchemaCheckSTPropsCorrect:
13362 * @ctxt: the schema parser context
13363 * @type: the simple type definition
13364 *
13365 * Checks st-props-correct.
13366 *
13367 * Returns 0 if the properties are correct,
13368 * if not, a positive error code and -1 on internal
13369 * errors.
13370 */
13371static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013372xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013373 xmlSchemaTypePtr type)
13374{
13375 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13376 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013377 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013378
Daniel Veillardc0826a72004-08-10 14:17:33 +000013379 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013380 /*
13381 * Schema Component Constraint: Simple Type Definition Properties Correct
13382 *
13383 * NOTE: This is somehow redundant, since we actually built a simple type
13384 * to have all the needed information; this acts as an self test.
13385 */
13386 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13387 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013388 /* Base type: If the datatype has been ·derived· by ·restriction·
13389 * then the Simple Type Definition component from which it is ·derived·,
13390 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013391 */
13392 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013393 /*
13394 * TODO: Think about: "modulo the impact of Missing
13395 * Sub-components (§5.3)."
13396 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013397 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013398 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013399 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013400 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013401 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013402
Daniel Veillard01fa6152004-06-29 17:04:39 +000013403 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013404 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013405 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013406 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013407 NULL, type, NULL,
13408 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013409 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013410 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013411 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13412 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013413 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13414 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13415 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013416 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013418 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013419 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013420 "the simple ur-type definition as base type, not '%s'",
13421 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013422 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013423 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13424 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013425 /*
13426 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013428 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13429 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013430 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013431 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013432 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013433 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013434 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13435 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013436 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013437
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013438 /*
13439 * 3 The {final} of the {base type definition} must not contain restriction.
13440 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013441 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013442 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13443 xmlSchemaPCustomErr(ctxt,
13444 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013445 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013446 "The 'final' of its base type '%s' must not contain "
13447 "'restriction'",
13448 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013449 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013450 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013451 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013452
13453 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013454 * 2 All simple type definitions must be derived ultimately from the ·simple
13455 * ur-type definition (so· circular definitions are disallowed). That is, it
13456 * must be possible to reach a built-in primitive datatype or the ·simple
13457 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013458 *
13459 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013460 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013461 return (0);
13462}
13463
13464/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013465 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013466 * @ctxt: the schema parser context
13467 * @type: the simple type definition
13468 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013469 * Schema Component Constraint:
13470 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13471
13472 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013473 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013474 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013475 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013476 * a positive error code otherwise.
13477 */
13478static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013479xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013480 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013481{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013482 xmlChar *str = NULL;
13483
Daniel Veillard01fa6152004-06-29 17:04:39 +000013484 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013485 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13486 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013487 return (-1);
13488 }
13489
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013491 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013492 /*
13493 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013494 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013495 */
13496 if (! VARIETY_ATOMIC(type->baseType)) {
13497 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013498 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013499 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013500 "The base type '%s' is not an atomic simple type",
13501 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013502 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013503 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13504 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013505 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013506 * restriction.
13507 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013508 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013509 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013510 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013511 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013512 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013513 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013514 "The final of its base type '%s' must not contain 'restriction'",
13515 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013516 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013517 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13518 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013519
13520 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013521 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013522 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013523 * Primitive datatypes.
13524 */
13525 if (type->facets != NULL) {
13526 xmlSchemaFacetPtr facet;
13527 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013528
Daniel Veillard01fa6152004-06-29 17:04:39 +000013529 primitive = xmlSchemaGetPrimitiveType(type);
13530 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013531 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13532 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013533 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013535 facet = type->facets;
13536 do {
13537 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013538 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013539 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013540 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013541 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013542 }
13543 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013544 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013545 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013546 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013547 }
13548 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013549 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13550 * of the {base type definition} (call this BF),then the DF's {value}
13551 * must be a valid restriction of BF's {value} as defined in
13552 * [XML Schemas: Datatypes]."
13553 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013554 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013555 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013556 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013557 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013558 xmlSchemaTypePtr itemType = NULL;
13559
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013560 itemType = type->subtypes;
13561 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013562 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13563 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013564 return (-1);
13565 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013566 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013567 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013568 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013569 * 2.1 The {item type definition} must have a {variety} of atomic or
13570 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013571 * must be atomic).
13572 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013573 if ((! VARIETY_ATOMIC(itemType)) &&
13574 (! VARIETY_UNION(itemType))) {
13575 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013576 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013577 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013578 "The item type '%s' does not have a variety of atomic or union",
13579 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013580 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013581 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013582 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013583 xmlSchemaTypeLinkPtr member;
13584
13585 member = itemType->memberTypes;
13586 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013587 if (! VARIETY_ATOMIC(member->type)) {
13588 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013589 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013590 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013591 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013592 "member type '%s' of this item type is not atomic",
13593 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013594 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013595 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13596 }
13597 member = member->next;
13598 }
13599 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013600
13601 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013602 xmlSchemaFacetPtr facet;
13603 /*
13604 * This is the case if we have: <simpleType><list ..
13605 */
13606 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013607 * 2.3.1
13608 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013609 * contain list.
13610 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013611 if (xmlSchemaTypeFinalContains(itemType,
13612 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13613 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013614 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013615 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013616 "The final of its item type '%s' must not contain 'list'",
13617 xmlSchemaGetComponentQName(&str, itemType));
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_1_1);
13620 }
13621 /*
13622 * 2.3.1.2 The {facets} must only contain the whiteSpace
13623 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013624 * OPTIMIZE TODO: the S4S already disallows any facet
13625 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013626 */
13627 if (type->facets != NULL) {
13628 facet = type->facets;
13629 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013630 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013631 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013632 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013633 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013634 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13635 }
13636 facet = facet->next;
13637 } while (facet != NULL);
13638 }
13639 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013640 * MAYBE TODO: (Hmm, not really) Datatypes states:
13641 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13642 * whose ·lexical space· allows space (such as string or anyURI)or
13643 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013644 * ·lexical space· allows space.
13645 */
13646 } else {
13647 /*
13648 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013649 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013650 */
13651 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013652 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013653 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13654 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013655 if (! VARIETY_LIST(type->baseType)) {
13656 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013657 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013658 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013659 "The base type '%s' must be a list type",
13660 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013661 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013662 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13663 }
13664 /*
13665 * 2.3.2.2 The {final} of the {base type definition} must not
13666 * contain restriction.
13667 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013668 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013669 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013670 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013671 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013672 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013673 "The 'final' of the base type '%s' must not contain 'restriction'",
13674 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013675 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013676 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13677 }
13678 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013679 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013680 * from the {base type definition}'s {item type definition} given
13681 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13682 */
13683 {
13684 xmlSchemaTypePtr baseItemType;
13685
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013686 baseItemType = type->baseType->subtypes;
13687 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013688 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13689 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013690 return (-1);
13691 }
13692 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013693 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13694 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013695 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013696 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013697 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013698 NULL, type, NULL,
13699 "The item type '%s' is not validly derived from "
13700 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013701 xmlSchemaGetComponentQName(&str, itemType),
13702 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13703 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013704
13705 FREE_AND_NULL(str)
13706 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013707 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013708 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13709 }
13710 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013711
Daniel Veillard01fa6152004-06-29 17:04:39 +000013712 if (type->facets != NULL) {
13713 xmlSchemaFacetPtr facet;
13714 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013715 /*
13716 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013717 * and enumeration facet components are allowed among the {facets}.
13718 */
13719 facet = type->facets;
13720 do {
13721 switch (facet->type) {
13722 case XML_SCHEMA_FACET_LENGTH:
13723 case XML_SCHEMA_FACET_MINLENGTH:
13724 case XML_SCHEMA_FACET_MAXLENGTH:
13725 case XML_SCHEMA_FACET_WHITESPACE:
13726 /*
13727 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013728 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013729 */
13730 case XML_SCHEMA_FACET_PATTERN:
13731 case XML_SCHEMA_FACET_ENUMERATION:
13732 break;
13733 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013734 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013735 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013736 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013737 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013738 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013739 * invalid facets.
13740 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013741 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013742 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013743 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013744 facet = facet->next;
13745 } while (facet != NULL);
13746 if (ok == 0)
13747 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13748 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013749 * SPEC (2.3.2.5) (same as 1.3.2)
13750 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013751 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013752 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013753 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013754 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013755 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013756 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013757 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013758 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013759 * atomic or list.
13760 */
13761 xmlSchemaTypeLinkPtr member;
13762
13763 member = type->memberTypes;
13764 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013765 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013766 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013767
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013768 if ((! VARIETY_ATOMIC(member->type)) &&
13769 (! VARIETY_LIST(member->type))) {
13770 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013771 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013772 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013773 "The member type '%s' is neither an atomic, nor a list type",
13774 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013775 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013776 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13777 }
13778 member = member->next;
13779 }
13780 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013781 * 3.3.1 If the {base type definition} is the ·simple ur-type
13782 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013783 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013784 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013785 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013786 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 * {final} which does not contain union.
13788 */
13789 member = type->memberTypes;
13790 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013791 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013792 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013793 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013794 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013795 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013796 "The 'final' of member type '%s' contains 'union'",
13797 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013798 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013799 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13800 }
13801 member = member->next;
13802 }
13803 /*
13804 * 3.3.1.2 The {facets} must be empty.
13805 */
13806 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013807 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013808 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013809 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013810 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013811 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13812 }
13813 } else {
13814 /*
13815 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013816 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013817 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013818 if (! VARIETY_UNION(type->baseType)) {
13819 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013820 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013821 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013822 "The base type '%s' is not a union type",
13823 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013824 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013825 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13826 }
13827 /*
13828 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13829 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013830 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013831 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013832 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013833 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013834 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013835 "The 'final' of its base type '%s' must not contain 'restriction'",
13836 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013837 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013838 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13839 }
13840 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013841 * 3.3.2.3 The {member type definitions}, in order, must be validly
13842 * derived from the corresponding type definitions in the {base
13843 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013844 * as defined in Type Derivation OK (Simple) (§3.14.6).
13845 */
13846 {
13847 xmlSchemaTypeLinkPtr baseMember;
13848
13849 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013850 * OPTIMIZE: if the type is restricting, it has no local defined
13851 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013852 * thus a check for equality can be skipped.
13853 */
13854 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013855 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013856 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013857 * types of it's base type. This check seems not necessary with
13858 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013859 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013860 */
13861 if (type->memberTypes != NULL) {
13862 member = type->memberTypes;
13863 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013864 if ((member == NULL) && (baseMember != NULL)) {
13865 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13866 "different number of member types in base");
13867 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013868 while (member != NULL) {
13869 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013870 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13871 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013872 }
13873 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013874 (xmlSchemaCheckCOSSTDerivedOK(
13875 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013876 xmlChar *strBMT = NULL, *strBT = NULL;
13877
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013878 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013879 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13880 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013881 "The member type %s is not validly "
13882 "derived from its corresponding member "
13883 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013884 xmlSchemaGetComponentQName(&str, member->type),
13885 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13886 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013887 FREE_AND_NULL(str)
13888 FREE_AND_NULL(strBMT)
13889 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013890 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013891 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013892 member = member->next;
13893 baseMember = baseMember->next;
13894 }
13895 }
13896 }
13897 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013898 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013899 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013900 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013901 if (type->facets != NULL) {
13902 xmlSchemaFacetPtr facet;
13903 int ok = 1;
13904
13905 facet = type->facets;
13906 do {
13907 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13908 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013909 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013910 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013911 NULL, type, facet);
13912 ok = 0;
13913 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013914 facet = facet->next;
13915 } while (facet != NULL);
13916 if (ok == 0)
13917 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013918
Daniel Veillard01fa6152004-06-29 17:04:39 +000013919 }
13920 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013921 * SPEC (3.3.2.5) (same as 1.3.2)
13922 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013923 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013924 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013925 */
13926 }
13927 }
13928
13929 return (0);
13930}
13931
13932/**
13933 * xmlSchemaCheckSRCSimpleType:
13934 * @ctxt: the schema parser context
13935 * @type: the simple type definition
13936 *
13937 * Checks crc-simple-type constraints.
13938 *
13939 * Returns 0 if the constraints are satisfied,
13940 * if not a positive error code and -1 on internal
13941 * errors.
13942 */
13943static int
13944xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13945 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013946{
13947 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013948 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013949 * must satisfy the conditions set out in Constraints on Simple Type
13950 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013951 */
13952 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13953 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13954 /*
13955 * TODO: Removed this, since it got annoying to get an
13956 * extra error report, if anything failed until now.
13957 * Enable this if needed.
13958 */
13959 /*
13960 xmlSchemaPErr(ctxt, type->node,
13961 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013962 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013963 "on simple type definitions.\n",
13964 type->name, NULL);
13965 */
13966 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13967 }
13968
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013969 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013970 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013971 * src-simple-type.2 If the <restriction> alternative is chosen,
13972 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013973 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013974 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013975 /*
13976 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013977 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013978 */
13979 } else if (VARIETY_LIST(type)) {
13980 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13981 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013982 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013983 *
13984 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013985 */
13986 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013987 xmlSchemaTypeLinkPtr member;
13988 xmlSchemaTypePtr ancestor, anySimpleType;
13989
13990 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13991
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013992 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13993 * the <union> alternative is chosen, there must not be any entries
13994 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000013995 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013996 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013997 member = type->memberTypes;
13998 while (member != NULL) {
13999 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014000 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014001 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014002 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014003 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014004 NULL, type, NULL,
14005 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014006 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014007 }
14008 if (IS_NOT_TYPEFIXED(ancestor))
14009 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014010 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014011 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014012 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014013 * type as item type, which in turn has a list ST as member
14014 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000014015 * was not yet performed.
14016 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014017 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014018
Daniel Veillard01fa6152004-06-29 17:04:39 +000014019 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014020 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014021 member = member->next;
14022 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014023 }
14024
14025 return (0);
14026}
14027
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014028static int
14029xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14030{
14031 if (ctxt->vctxt == NULL) {
14032 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14033 if (ctxt->vctxt == NULL) {
14034 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014035 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014036 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014037 "failed to create a temp. validation context.\n",
14038 NULL, NULL);
14039 return (-1);
14040 }
14041 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014042 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014043 }
14044 return (0);
14045}
14046
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014047static int
14048xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14049 xmlNodePtr node,
14050 xmlSchemaTypePtr type,
14051 const xmlChar *value,
14052 xmlSchemaValPtr *retVal,
14053 int fireErrors,
14054 int normalize,
14055 int isNormalized);
14056
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014057/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014058 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014059 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014060 * @type: the simple type definition
14061 * @value: the default value
14062 * @node: an optional node (the holder of the value)
14063 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014064 * Schema Component Constraint: Element Default Valid (Immediate)
14065 * (cos-valid-default)
14066 * This will be used by the parser only. For the validator there's
14067 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014068 *
14069 * Returns 0 if the constraints are satisfied,
14070 * if not, a positive error code and -1 on internal
14071 * errors.
14072 */
14073static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014074xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14075 xmlNodePtr node,
14076 xmlSchemaTypePtr type,
14077 const xmlChar *value,
14078 xmlSchemaValPtr *val)
14079{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014080 int ret = 0;
14081
14082 /*
14083 * cos-valid-default:
14084 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014085 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014086 * definition the appropriate case among the following must be true:
14087 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014088 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014089 /*
14090 * Complex type.
14091 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014092 * SPEC (2.1) "its {content type} must be a simple type definition
14093 * or mixed."
14094 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014095 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014096 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014097 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014098 if ((! HAS_SIMPLE_CONTENT(type)) &&
14099 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14100 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014101 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014102 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014103 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014104 "For a string to be a valid default, the type definition "
14105 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014106 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014107 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14108 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014109 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014110 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014111 * 1 If the type definition is a simple type definition, then the string
14112 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014113 * Valid (§3.14.4).
14114 *
14115 * AND
14116 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014117 * 2.2.1 If the {content type} is a simple type definition, then the
14118 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014119 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014120 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014121 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014122 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14123 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014124 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014125 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14126 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014127 else
14128 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014129
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014130 if (ret < 0) {
14131 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14132 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014133 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014134
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014135 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014136}
14137
14138/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014139 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014140 * @ctxt: the schema parser context
14141 * @type: the complex type definition
14142 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014143 *.(4.6) Constraints on Complex Type Definition Schema Components
14144 * Schema Component Constraint:
14145 * Complex Type Definition Properties Correct (ct-props-correct)
14146 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014147 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014148 * Returns 0 if the constraints are satisfied, a positive
14149 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014150 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014151static int
14152xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14153 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014154{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014155 /*
14156 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14157 *
14158 * SPEC (1) "The values of the properties of a complex type definition must
14159 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014160 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014161 * Sub-components (§5.3)."
14162 */
14163 if ((type->baseType != NULL) &&
14164 (IS_SIMPLE_TYPE(type->baseType)) &&
14165 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14166 /*
14167 * SPEC (2) "If the {base type definition} is a simple type definition,
14168 * the {derivation method} must be extension."
14169 */
14170 xmlSchemaPCustomErr(pctxt,
14171 XML_SCHEMAP_SRC_CT_1,
14172 NULL, type, NULL,
14173 "If the base type is a simple type, the derivation method must be "
14174 "'extension'", NULL);
14175 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014176 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014177 /*
14178 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14179 * definition·. That is, it must be possible to reach the ·ur-type
14180 * definition by repeatedly following the {base type definition}."
14181 *
14182 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14183 *
14184 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014185 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014186 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14187 * must not have {type definition}s which are or are derived from ID."
14188 *
14189 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14190 */
14191 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014192}
14193
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014194static int
14195xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14196 xmlSchemaTypePtr typeB)
14197{
14198 /*
14199 * TODO: This should implement component-identity
14200 * in the future.
14201 */
14202 if ((typeA == NULL) || (typeB == NULL))
14203 return (0);
14204 return (typeA == typeB);
14205}
14206
14207/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014208 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014209 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014210 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014211 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014212 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014213 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014214 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014215 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14216 *
14217 * STATUS: completed
14218 *
14219 * Returns 0 if the constraints are satisfied, or 1
14220 * if not.
14221 */
14222static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014223xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014224 xmlSchemaTypePtr baseType,
14225 int set)
14226{
14227 int equal = xmlSchemaAreEqualTypes(type, baseType);
14228 /* TODO: Error codes. */
14229 /*
14230 * SPEC "For a complex type definition (call it D, for derived)
14231 * to be validly derived from a type definition (call this
14232 * B, for base) given a subset of {extension, restriction}
14233 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014234 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014235 if (! equal) {
14236 /*
14237 * SPEC (1) "If B and D are not the same type definition, then the
14238 * {derivation method} of D must not be in the subset."
14239 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014240 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014241 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014242 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014243 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014244 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014245 } else {
14246 /*
14247 * SPEC (2.1) "B and D must be the same type definition."
14248 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014249 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014250 }
14251 /*
14252 * SPEC (2.2) "B must be D's {base type definition}."
14253 */
14254 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014255 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014256 /*
14257 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14258 * definition·."
14259 */
14260 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014261 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014262
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014263 if (IS_COMPLEX_TYPE(type->baseType)) {
14264 /*
14265 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14266 * must be validly derived from B given the subset as defined by this
14267 * constraint."
14268 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014269 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014270 baseType, set));
14271 } else {
14272 /*
14273 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14274 * must be validly derived from B given the subset as defined in Type
14275 * Derivation OK (Simple) (§3.14.6).
14276 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014277 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14278 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014279}
14280
14281/**
14282 * xmlSchemaCheckCOSDerivedOK:
14283 * @type: the derived simple type definition
14284 * @baseType: the base type definition
14285 *
14286 * Calls:
14287 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014288 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014289 * Checks wheter @type can be validly derived from @baseType.
14290 *
14291 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014292 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014293static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014294xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014295 xmlSchemaTypePtr baseType,
14296 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014297{
14298 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014299 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014300 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014301 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014302}
14303
William M. Brack2f2a6632004-08-20 23:09:47 +000014304/**
14305 * xmlSchemaCheckCOSCTExtends:
14306 * @ctxt: the schema parser context
14307 * @type: the complex type definition
14308 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014309 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014310 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014311 * Derivation Valid (Extension) (cos-ct-extends)
14312 *
14313 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014314 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014315 * (1.5)
14316 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014317 *
14318 * Returns 0 if the constraints are satisfied, a positive
14319 * error code if not and -1 if an internal error occured.
14320 */
14321static int
14322xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14323 xmlSchemaTypePtr type)
14324{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014325 xmlSchemaTypePtr base = type->baseType;
14326 /*
14327 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14328 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014329 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014330 /*
14331 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014332 * then all of the following must be true:"
14333 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014334 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14335 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014336 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014337 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014338 */
14339 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14340 xmlSchemaPCustomErr(ctxt,
14341 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14342 NULL, type, NULL,
14343 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014344 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014345 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14346 }
14347 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014348 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014349 * uses}
14350 * of the complex type definition itself, that is, for every attribute
14351 * use in the {attribute uses} of the {base type definition}, there
14352 * must be an attribute use in the {attribute uses} of the complex
14353 * type definition itself whose {attribute declaration} has the same
14354 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014355 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014356 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014357 * NOTE (1.2): This will be already satisfied by the way the attribute
14358 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14359 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014360 */
14361
14362 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014363 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14364 * definition must also have one, and the base type definition's
14365 * {attribute wildcard}'s {namespace constraint} must be a subset
14366 * of the complex type definition's {attribute wildcard}'s {namespace
14367 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014368 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014369 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014370 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014371 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014372 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014373 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014374 if ((type->contentTypeDef != NULL) &&
14375 (type->contentTypeDef == base->contentTypeDef)) {
14376 /*
14377 * SPEC (1.4.1) "The {content type} of the {base type definition}
14378 * and the {content type} of the complex type definition itself
14379 * must be the same simple type definition"
14380 * PASS
14381 */
14382 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14383 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14384 /*
14385 * SPEC (1.4.2) "The {content type} of both the {base type
14386 * definition} and the complex type definition itself must
14387 * be empty."
14388 * PASS
14389 */
14390 } else {
14391 /*
14392 * SPEC (1.4.3) "All of the following must be true:"
14393 */
14394 if (type->subtypes == NULL) {
14395 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014396 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014397 * definition itself must specify a particle.
14398 */
14399 xmlSchemaPCustomErr(ctxt,
14400 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14401 NULL, type, NULL,
14402 "The content type must specify a particle", NULL);
14403 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14404 }
14405 /*
14406 * SPEC (1.4.3.2) "One of the following must be true:"
14407 */
14408 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14409 /*
14410 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14411 * definition} must be empty.
14412 * PASS
14413 */
14414 } else {
14415 /*
14416 * SPEC (1.4.3.2.2) "All of the following must be true:"
14417 */
14418 if ((type->contentType != base->contentType) ||
14419 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14420 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14421 /*
14422 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14423 * or both must be element-only."
14424 */
14425 xmlSchemaPCustomErr(ctxt,
14426 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14427 NULL, type, NULL,
14428 "The content type of both, the type and its base "
14429 "type, must either 'mixed' or 'element-only'", NULL);
14430 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014431 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014432 /*
14433 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14434 * complex type definition must be a ·valid extension·
14435 * of the {base type definition}'s particle, as defined
14436 * in Particle Valid (Extension) (§3.9.6)."
14437 *
14438 * NOTE that we won't check "Particle Valid (Extension)",
14439 * since it is ensured by the derivation process in
14440 * xmlSchemaTypeFixup(). We need to implement this when heading
14441 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014442 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014443 }
14444 /*
14445 * TODO (1.5)
14446 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014447 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014448 } else {
14449 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014450 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014451 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014452 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014453 if (type->contentTypeDef != base) {
14454 /*
14455 * SPEC (2.1) "The {content type} must be the same simple type
14456 * definition."
14457 */
14458 xmlSchemaPCustomErr(ctxt,
14459 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14460 NULL, type, NULL,
14461 "The content type must be the simple base type", NULL);
14462 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14463 }
14464 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14465 /*
14466 * SPEC (2.2) "The {final} of the {base type definition} must not
14467 * contain extension"
14468 * NOTE that this is the same as (1.1).
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 'extension'", NULL);
14475 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014476 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014477 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014478 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014479}
14480
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014481/**
14482 * xmlSchemaCheckDerivationOKRestriction:
14483 * @ctxt: the schema parser context
14484 * @type: the complex type definition
14485 *
14486 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014487 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014488 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14489 *
14490 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014491 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014492 * (5.4.2), (5.2.2.1)
14493 *
14494 * Returns 0 if the constraints are satisfied, a positive
14495 * error code if not and -1 if an internal error occured.
14496 */
14497static int
14498xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14499 xmlSchemaTypePtr type)
14500{
14501 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014502
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014503 /*
14504 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14505 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014506 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014507 base = type->baseType;
14508 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14509 /*
14510 * SPEC (1) "The {base type definition} must be a complex type
14511 * definition whose {final} does not contain restriction."
14512 */
14513 xmlSchemaPCustomErr(ctxt,
14514 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14515 NULL, type, NULL,
14516 "The 'final' of the base type definition "
14517 "contains 'restriction'", NULL);
14518 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14519 }
14520 /*
14521 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14522 *
14523 * SPEC (5) "One of the following must be true:"
14524 */
14525 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14526 /*
14527 * SPEC (5.1) "The {base type definition} must be the
14528 * ·ur-type definition·."
14529 * PASS
14530 */
14531 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14532 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14533 /*
14534 * SPEC (5.2.1) "The {content type} of the complex type definition
14535 * must be a simple type definition"
14536 *
14537 * SPEC (5.2.2) "One of the following must be true:"
14538 */
14539 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14540 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14541 /*
14542 * SPEC (5.2.2.1) "The {content type} of the {base type
14543 * definition} must be a simple type definition from which
14544 * the {content type} is validly derived given the empty
14545 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14546 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014547 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014548 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14549 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014550 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014551 /*
14552 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14553 * and have a particle which is ·emptiable· as defined in
14554 * Particle Emptiable (§3.9.6)."
14555 * PASS
14556 */
14557 } else {
14558 xmlSchemaPCustomErr(ctxt,
14559 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14560 NULL, type, NULL,
14561 "The content type of the base type must be either "
14562 "a simple type or 'mixed' and an emptiable particle", NULL);
14563 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14564 }
14565 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14566 /*
14567 * SPEC (5.3.1) "The {content type} of the complex type itself must
14568 * be empty"
14569 */
14570 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14571 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014572 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014573 * definition} must also be empty."
14574 * PASS
14575 */
14576 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14577 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14578 xmlSchemaIsParticleEmptiable(
14579 (xmlSchemaParticlePtr) base->subtypes)) {
14580 /*
14581 * SPEC (5.3.2.2) "The {content type} of the {base type
14582 * definition} must be elementOnly or mixed and have a particle
14583 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14584 * PASS
14585 */
14586 } else {
14587 xmlSchemaPCustomErr(ctxt,
14588 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14589 NULL, type, NULL,
14590 "The content type of the base type must be either "
14591 "empty or 'mixed' (or 'elements-only') and an emptiable "
14592 "particle", NULL);
14593 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14594 }
14595 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014596 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014597 /*
14598 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14599 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014600 */
14601 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14602 /*
14603 * SPEC (5.4.1.2) "The {content type} of the complex type
14604 * definition itself and of the {base type definition} must be
14605 * mixed"
14606 */
14607 xmlSchemaPCustomErr(ctxt,
14608 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14609 NULL, type, NULL,
14610 "If the content type is 'mixed', then the content type of the "
14611 "base type must also be 'mixed'", NULL);
14612 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14613 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014614 /*
14615 * SPEC (5.4.2) "The particle of the complex type definition itself
14616 * must be a ·valid restriction· of the particle of the {content
14617 * type} of the {base type definition} as defined in Particle Valid
14618 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014619 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014620 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014621 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014622 } else {
14623 xmlSchemaPCustomErr(ctxt,
14624 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14625 NULL, type, NULL,
14626 "The type is not a valid restriction of its base type", NULL);
14627 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14628 }
14629 return (0);
14630}
14631
14632/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014633 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014634 * @ctxt: the schema parser context
14635 * @type: the complex type definition
14636 *
14637 * (3.4.6) Constraints on Complex Type Definition Schema Components
14638 *
14639 * Returns 0 if the constraints are satisfied, a positive
14640 * error code if not and -1 if an internal error occured.
14641 */
14642static int
14643xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14644 xmlSchemaTypePtr type)
14645{
14646 int ret;
14647 /*
14648 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014649 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014650 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14651 if (ret != 0)
14652 return (ret);
14653 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14654 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14655 else
14656 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14657 return (ret);
14658}
14659
14660/**
14661 * xmlSchemaCheckSRCCT:
14662 * @ctxt: the schema parser context
14663 * @type: the complex type definition
14664 *
14665 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014666 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014667 * Complex Type Definition Representation OK (src-ct)
14668 *
14669 * Returns 0 if the constraints are satisfied, a positive
14670 * error code if not and -1 if an internal error occured.
14671 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014672static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014673xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014674 xmlSchemaTypePtr type)
14675{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014676 xmlSchemaTypePtr base;
14677 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014678
14679 /*
14680 * TODO: Adjust the error codes here, as I used
14681 * XML_SCHEMAP_SRC_CT_1 only yet.
14682 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014683 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014684 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014685 /*
14686 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014687 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014688 * must be a complex type definition;
14689 */
14690 if (! IS_COMPLEX_TYPE(base)) {
14691 xmlChar *str = NULL;
14692 xmlSchemaPCustomErr(ctxt,
14693 XML_SCHEMAP_SRC_CT_1,
14694 NULL, type, type->node,
14695 "If using <complexContent>, the base type is expected to be "
14696 "a complex type. The base type '%s' is a simple type",
14697 xmlSchemaFormatQName(&str, base->targetNamespace,
14698 base->name));
14699 FREE_AND_NULL(str)
14700 return (XML_SCHEMAP_SRC_CT_1);
14701 }
14702 } else {
14703 /*
14704 * SPEC
14705 * 2 If the <simpleContent> alternative is chosen, all of the
14706 * following must be true:
14707 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14708 * base [attribute] must be one of the following:
14709 */
14710 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014711 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014712 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14713 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014714 /*
14715 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014716 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014717 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014718 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014719 xmlSchemaPCustomErr(ctxt,
14720 XML_SCHEMAP_SRC_CT_1,
14721 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014722 "If using <simpleContent> and <restriction>, the base "
14723 "type must be a complex type. The base type '%s' is "
14724 "a simple type",
14725 xmlSchemaFormatQName(&str, base->targetNamespace,
14726 base->name));
14727 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014728 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014729 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014730 } else {
14731 /* Base type is a complex type. */
14732 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14733 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14734 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014735 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014736 * simple type definition;
14737 * PASS
14738 */
14739 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014740 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014741 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014742 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014743 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014744 type->name);
14745 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014746 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014747 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14748 (type->flags &
14749 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014750
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014751 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014752 * 2.1.2 only if the <restriction> alternative is also
14753 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014754 * is mixed and a particle emptiable.
14755 */
14756 if (! xmlSchemaIsParticleEmptiable(
14757 (xmlSchemaParticlePtr) base->subtypes)) {
14758 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014759 } else
14760 /*
14761 * Attention: at this point the <simpleType> child is in
14762 * ->contentTypeDef (put there during parsing).
14763 */
14764 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014765 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014766 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014767 * 2.2 If clause 2.1.2 above is satisfied, then there
14768 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014769 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014770 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014771 /* TODO: Change error code to ..._SRC_CT_2_2. */
14772 xmlSchemaPCustomErr(ctxt,
14773 XML_SCHEMAP_SRC_CT_1,
14774 NULL, type, NULL,
14775 "A <simpleType> is expected among the children "
14776 "of <restriction>, if <simpleContent> is used and "
14777 "the base type '%s' is a complex type",
14778 xmlSchemaFormatQName(&str, base->targetNamespace,
14779 base->name));
14780 FREE_AND_NULL(str)
14781 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014782 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014783 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014784 ret = XML_SCHEMAP_SRC_CT_1;
14785 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014786 }
14787 if (ret > 0) {
14788 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014789 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014790 xmlSchemaPCustomErr(ctxt,
14791 XML_SCHEMAP_SRC_CT_1,
14792 NULL, type, NULL,
14793 "If <simpleContent> and <restriction> is used, the "
14794 "base type must be a simple type or a complex type with "
14795 "mixed content and particle emptiable. The base type "
14796 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014797 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014798 base->name));
14799 } else {
14800 xmlSchemaPCustomErr(ctxt,
14801 XML_SCHEMAP_SRC_CT_1,
14802 NULL, type, NULL,
14803 "If <simpleContent> and <extension> is used, the "
14804 "base type must be a simple type. The base type '%s' "
14805 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014806 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014807 base->name));
14808 }
14809 FREE_AND_NULL(str)
14810 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014811 }
14812 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014813 * SPEC (3) "The corresponding complex type definition component must
14814 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014815 * Definition Schema Components (§3.4.6);"
14816 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014817 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014818 /*
14819 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014820 * above for {attribute wildcard} is satisfied, the intensional
14821 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014822 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014823 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014824 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014825 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014826}
William M. Brack2f2a6632004-08-20 23:09:47 +000014827
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014828#ifdef ENABLE_PARTICLE_RESTRICTION
14829/**
14830 * xmlSchemaCheckParticleRangeOK:
14831 * @ctxt: the schema parser context
14832 * @type: the complex type definition
14833 *
14834 * (3.9.6) Constraints on Particle Schema Components
14835 * Schema Component Constraint:
14836 * Occurrence Range OK (range-ok)
14837 *
14838 * STATUS: complete
14839 *
14840 * Returns 0 if the constraints are satisfied, a positive
14841 * error code if not and -1 if an internal error occured.
14842 */
14843static int
14844xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14845 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014846{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014847 if (rmin < bmin)
14848 return (1);
14849 if ((bmax != UNBOUNDED) &&
14850 (rmax > bmax))
14851 return (1);
14852 return (0);
14853}
14854
14855/**
14856 * xmlSchemaCheckRCaseNameAndTypeOK:
14857 * @ctxt: the schema parser context
14858 * @r: the restricting element declaration particle
14859 * @b: the base element declaration particle
14860 *
14861 * (3.9.6) Constraints on Particle Schema Components
14862 * Schema Component Constraint:
14863 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14864 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014865 *
14866 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014867 * MISSING (3.2.3)
14868 * CLARIFY: (3.2.2)
14869 *
14870 * Returns 0 if the constraints are satisfied, a positive
14871 * error code if not and -1 if an internal error occured.
14872 */
14873static int
14874xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14875 xmlSchemaParticlePtr r,
14876 xmlSchemaParticlePtr b)
14877{
14878 xmlSchemaElementPtr elemR, elemB;
14879
14880 /* TODO: Error codes (rcase-NameAndTypeOK). */
14881 elemR = (xmlSchemaElementPtr) r->children;
14882 elemB = (xmlSchemaElementPtr) b->children;
14883 /*
14884 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14885 * the same."
14886 */
14887 if ((elemR != elemB) &&
14888 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14889 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14890 return (1);
14891 /*
14892 * SPEC (2) "R's occurrence range is a valid restriction of B's
14893 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14894 */
14895 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14896 b->minOccurs, b->maxOccurs) != 0)
14897 return (1);
14898 /*
14899 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14900 * {scope} are global."
14901 */
14902 if (elemR == elemB)
14903 return (0);
14904 /*
14905 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14906 */
14907 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14908 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14909 return (1);
14910 /*
14911 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14912 * or is not fixed, or R's declaration's {value constraint} is fixed
14913 * with the same value."
14914 */
14915 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14916 ((elemR->value == NULL) ||
14917 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14918 /* TODO: Equality of the initial value or normalized or canonical? */
14919 (! xmlStrEqual(elemR->value, elemB->value))))
14920 return (1);
14921 /*
14922 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14923 * definitions} is a subset of B's declaration's {identity-constraint
14924 * definitions}, if any."
14925 */
14926 if (elemB->idcs != NULL) {
14927 /* TODO */
14928 }
14929 /*
14930 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14931 * superset of B's declaration's {disallowed substitutions}."
14932 */
14933 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14934 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14935 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14936 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14937 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14938 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14939 return (1);
14940 /*
14941 * SPEC (3.2.5) "R's {type definition} is validly derived given
14942 * {extension, list, union} from B's {type definition}"
14943 *
14944 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14945 * set, if the corresponding constraints handle "restriction" and
14946 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014947 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014948 */
14949 {
14950 int set = 0;
14951
14952 set |= SUBSET_EXTENSION;
14953 set |= SUBSET_LIST;
14954 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014955 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014956 elemB->subtypes, set) != 0)
14957 return (1);
14958 }
14959 return (0);
14960}
14961
14962/**
14963 * xmlSchemaCheckRCaseNSCompat:
14964 * @ctxt: the schema parser context
14965 * @r: the restricting element declaration particle
14966 * @b: the base wildcard particle
14967 *
14968 * (3.9.6) Constraints on Particle Schema Components
14969 * Schema Component Constraint:
14970 * Particle Derivation OK (Elt:Any -- NSCompat)
14971 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014972 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014973 * STATUS: complete
14974 *
14975 * Returns 0 if the constraints are satisfied, a positive
14976 * error code if not and -1 if an internal error occured.
14977 */
14978static int
14979xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14980 xmlSchemaParticlePtr r,
14981 xmlSchemaParticlePtr b)
14982{
14983 /* TODO:Error codes (rcase-NSCompat). */
14984 /*
14985 * SPEC "For an element declaration particle to be a ·valid restriction·
14986 * of a wildcard particle all of the following must be true:"
14987 *
14988 * SPEC (1) "The element declaration's {target namespace} is ·valid·
14989 * with respect to the wildcard's {namespace constraint} as defined by
14990 * Wildcard allows Namespace Name (§3.10.4)."
14991 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014992 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014993 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
14994 return (1);
14995 /*
14996 * SPEC (2) "R's occurrence range is a valid restriction of B's
14997 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14998 */
14999 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15000 b->minOccurs, b->maxOccurs) != 0)
15001 return (1);
15002
15003 return (0);
15004}
15005
15006/**
15007 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15008 * @ctxt: the schema parser context
15009 * @r: the restricting element declaration particle
15010 * @b: the base model group particle
15011 *
15012 * (3.9.6) Constraints on Particle Schema Components
15013 * Schema Component Constraint:
15014 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15015 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015016 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015017 * STATUS: TODO
15018 *
15019 * Returns 0 if the constraints are satisfied, a positive
15020 * error code if not and -1 if an internal error occured.
15021 */
15022static int
15023xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15024 xmlSchemaParticlePtr r,
15025 xmlSchemaParticlePtr b)
15026{
15027 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15028 TODO
15029 return (0);
15030}
15031
15032/**
15033 * xmlSchemaCheckRCaseNSSubset:
15034 * @ctxt: the schema parser context
15035 * @r: the restricting wildcard particle
15036 * @b: the base wildcard particle
15037 *
15038 * (3.9.6) Constraints on Particle Schema Components
15039 * Schema Component Constraint:
15040 * Particle Derivation OK (Any:Any -- NSSubset)
15041 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015042 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015043 * STATUS: complete
15044 *
15045 * Returns 0 if the constraints are satisfied, a positive
15046 * error code if not and -1 if an internal error occured.
15047 */
15048static int
15049xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15050 xmlSchemaParticlePtr r,
15051 xmlSchemaParticlePtr b,
15052 int isAnyTypeBase)
15053{
15054 /* TODO: Error codes (rcase-NSSubset). */
15055 /*
15056 * SPEC (1) "R's occurrence range is a valid restriction of B's
15057 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15058 */
15059 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15060 b->minOccurs, b->maxOccurs))
15061 return (1);
15062 /*
15063 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15064 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15065 */
15066 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15067 (xmlSchemaWildcardPtr) b->children))
15068 return (1);
15069 /*
15070 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15071 * definition·, R's {process contents} must be identical to or stronger
15072 * than B's {process contents}, where strict is stronger than lax is
15073 * stronger than skip."
15074 */
15075 if (! isAnyTypeBase) {
15076 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15077 ((xmlSchemaWildcardPtr) b->children)->processContents)
15078 return (1);
15079 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015080
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015081 return (0);
15082}
15083
15084/**
15085 * xmlSchemaCheckCOSParticleRestrict:
15086 * @ctxt: the schema parser context
15087 * @type: the complex type definition
15088 *
15089 * (3.9.6) Constraints on Particle Schema Components
15090 * Schema Component Constraint:
15091 * Particle Valid (Restriction) (cos-particle-restrict)
15092 *
15093 * STATUS: TODO
15094 *
15095 * Returns 0 if the constraints are satisfied, a positive
15096 * error code if not and -1 if an internal error occured.
15097 */
15098static int
15099xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15100 xmlSchemaParticlePtr r,
15101 xmlSchemaParticlePtr b)
15102{
15103 int ret = 0;
15104
15105 /*part = GET_PARTICLE(type);
15106 basePart = GET_PARTICLE(base);
15107 */
15108
15109 TODO
15110
15111 /*
15112 * SPEC (1) "They are the same particle."
15113 */
15114 if (r == b)
15115 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015116
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015117
15118 return (0);
15119}
15120
15121/**
15122 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15123 * @ctxt: the schema parser context
15124 * @r: the model group particle
15125 * @b: the base wildcard particle
15126 *
15127 * (3.9.6) Constraints on Particle Schema Components
15128 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015129 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015130 * NSRecurseCheckCardinality)
15131 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015132 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015133 * STATUS: TODO: subst-groups
15134 *
15135 * Returns 0 if the constraints are satisfied, a positive
15136 * error code if not and -1 if an internal error occured.
15137 */
15138static int
15139xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15140 xmlSchemaParticlePtr r,
15141 xmlSchemaParticlePtr b)
15142{
15143 xmlSchemaParticlePtr part;
15144 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15145 if ((r->children == NULL) || (r->children->children == NULL))
15146 return (-1);
15147 /*
15148 * SPEC "For a group particle to be a ·valid restriction· of a
15149 * wildcard particle..."
15150 *
15151 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015152 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015153 * Particle Valid (Restriction) (§3.9.6)."
15154 */
15155 part = (xmlSchemaParticlePtr) r->children->children;
15156 do {
15157 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15158 return (1);
15159 part = (xmlSchemaParticlePtr) part->next;
15160 } while (part != NULL);
15161 /*
15162 * SPEC (2) "The effective total range of the group [...] is a
15163 * valid restriction of B's occurrence range as defined by
15164 * Occurrence Range OK (§3.9.6)."
15165 */
15166 if (xmlSchemaCheckParticleRangeOK(
15167 xmlSchemaGetParticleTotalRangeMin(r),
15168 xmlSchemaGetParticleTotalRangeMax(r),
15169 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015170 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015171 return (0);
15172}
15173
15174/**
15175 * xmlSchemaCheckRCaseRecurse:
15176 * @ctxt: the schema parser context
15177 * @r: the <all> or <sequence> model group particle
15178 * @b: the base <all> or <sequence> model group particle
15179 *
15180 * (3.9.6) Constraints on Particle Schema Components
15181 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015182 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015183 Recurse)
15184 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015185 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015186 * STATUS: ?
15187 * TODO: subst-groups
15188 *
15189 * Returns 0 if the constraints are satisfied, a positive
15190 * error code if not and -1 if an internal error occured.
15191 */
15192static int
15193xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15194 xmlSchemaParticlePtr r,
15195 xmlSchemaParticlePtr b)
15196{
15197 /* xmlSchemaParticlePtr part; */
15198 /* TODO: Error codes (rcase-Recurse). */
15199 if ((r->children == NULL) || (b->children == NULL) ||
15200 (r->children->type != b->children->type))
15201 return (-1);
15202 /*
15203 * SPEC "For an all or sequence group particle to be a ·valid
15204 * restriction· of another group particle with the same {compositor}..."
15205 *
15206 * SPEC (1) "R's occurrence range is a valid restriction of B's
15207 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15208 */
15209 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15210 b->minOccurs, b->maxOccurs))
15211 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015212
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015213
15214 return (0);
15215}
15216
15217#endif
15218
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015219#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15220 xmlSchemaPCustomErrExt(pctxt, \
15221 XML_SCHEMAP_INVALID_FACET_VALUE, \
15222 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15223 "It is an error for both '%s' and '%s' to be specified on the "\
15224 "same type definition", \
15225 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15226 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15227
15228#define FACET_RESTR_ERR(fac1, msg) \
15229 xmlSchemaPCustomErr(pctxt, \
15230 XML_SCHEMAP_INVALID_FACET_VALUE, \
15231 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015232 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015233
15234#define FACET_RESTR_FIXED_ERR(fac) \
15235 xmlSchemaPCustomErr(pctxt, \
15236 XML_SCHEMAP_INVALID_FACET_VALUE, \
15237 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15238 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015239 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015240
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015241static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015242xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15243 xmlSchemaFacetPtr facet1,
15244 xmlSchemaFacetPtr facet2,
15245 int lessGreater,
15246 int orEqual,
15247 int ofBase)
15248{
15249 xmlChar *msg = NULL;
15250
15251 msg = xmlStrdup(BAD_CAST "'");
15252 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15253 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15254 if (lessGreater == 0)
15255 msg = xmlStrcat(msg, BAD_CAST " equal to");
15256 if (lessGreater == 1)
15257 msg = xmlStrcat(msg, BAD_CAST " greater than");
15258 else
15259 msg = xmlStrcat(msg, BAD_CAST " less than");
15260
15261 if (orEqual)
15262 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15263 msg = xmlStrcat(msg, BAD_CAST " '");
15264 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15265 if (ofBase)
15266 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15267 else
15268 msg = xmlStrcat(msg, BAD_CAST "'");
15269
15270 xmlSchemaPCustomErr(pctxt,
15271 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015272 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015273 (const char *) msg, NULL);
15274
15275 if (msg != NULL)
15276 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015277}
15278
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015279static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015280xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15281 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015282{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015283 xmlSchemaTypePtr base = type->baseType;
15284 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015285 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015286 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15287 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15288 fmininc = NULL, fmaxinc = NULL,
15289 fminexc = NULL, fmaxexc = NULL,
15290 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15291 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15292 bfmininc = NULL, bfmaxinc = NULL,
15293 bfminexc = NULL, bfmaxexc = NULL;
15294 int res, err = 0, fixedErr;
15295 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015296 * 3 The {facets} of R are the union of S and the {facets}
15297 * of B, eliminating duplicates. To eliminate duplicates,
15298 * when a facet of the same kind occurs in both S and the
15299 * {facets} of B, the one in the {facets} of B is not
15300 * included, with the exception of enumeration and pattern
15301 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015302 * are allowed.
15303 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015305 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15306 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015307
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015308 last = type->facetSet;
15309 if (last != NULL)
15310 while (last->next != NULL)
15311 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015312
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015313 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15314 facet = cur->facet;
15315 switch (facet->type) {
15316 case XML_SCHEMA_FACET_LENGTH:
15317 flength = facet; break;
15318 case XML_SCHEMA_FACET_MINLENGTH:
15319 fminlen = facet; break;
15320 case XML_SCHEMA_FACET_MININCLUSIVE:
15321 fmininc = facet; break;
15322 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15323 fminexc = facet; break;
15324 case XML_SCHEMA_FACET_MAXLENGTH:
15325 fmaxlen = facet; break;
15326 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15327 fmaxinc = facet; break;
15328 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15329 fmaxexc = facet; break;
15330 case XML_SCHEMA_FACET_TOTALDIGITS:
15331 ftotdig = facet; break;
15332 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15333 ffracdig = facet; break;
15334 default:
15335 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015336 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015337 }
15338 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15339 facet = cur->facet;
15340 switch (facet->type) {
15341 case XML_SCHEMA_FACET_LENGTH:
15342 bflength = facet; break;
15343 case XML_SCHEMA_FACET_MINLENGTH:
15344 bfminlen = facet; break;
15345 case XML_SCHEMA_FACET_MININCLUSIVE:
15346 bfmininc = facet; break;
15347 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15348 bfminexc = facet; break;
15349 case XML_SCHEMA_FACET_MAXLENGTH:
15350 bfmaxlen = facet; break;
15351 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15352 bfmaxinc = facet; break;
15353 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15354 bfmaxexc = facet; break;
15355 case XML_SCHEMA_FACET_TOTALDIGITS:
15356 bftotdig = facet; break;
15357 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15358 bffracdig = facet; break;
15359 default:
15360 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015361 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015362 }
15363 err = 0;
15364 /*
15365 * length and minLength or maxLength (2.2) + (3.2)
15366 */
15367 if (flength && (fminlen || fmaxlen)) {
15368 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15369 "either of 'minLength' or 'maxLength' to be specified on "
15370 "the same type definition")
15371 }
15372 /*
15373 * Mutual exclusions in the same derivation step.
15374 */
15375 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015376 /*
15377 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015378 */
15379 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15380 }
15381 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015382 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015383 * SCC "minInclusive and minExclusive"
15384 */
15385 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015386 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015387
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015388 if (flength && bflength) {
15389 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015390 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015391 * The values have to be equal.
15392 */
15393 res = xmlSchemaCompareValues(flength->val, bflength->val);
15394 if (res == -2)
15395 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015396 if (res != 0)
15397 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15398 if ((res != 0) && (bflength->fixed)) {
15399 FACET_RESTR_FIXED_ERR(flength)
15400 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015401
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015402 }
15403 if (fminlen && bfminlen) {
15404 /*
15405 * SCC "minLength valid restriction"
15406 * minLength >= BASE minLength
15407 */
15408 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15409 if (res == -2)
15410 goto internal_error;
15411 if (res == -1)
15412 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15413 if ((res != 0) && (bfminlen->fixed)) {
15414 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015415 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015416 }
15417 if (fmaxlen && bfmaxlen) {
15418 /*
15419 * SCC "maxLength valid restriction"
15420 * maxLength <= BASE minLength
15421 */
15422 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15423 if (res == -2)
15424 goto internal_error;
15425 if (res == 1)
15426 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15427 if ((res != 0) && (bfmaxlen->fixed)) {
15428 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015429 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015430 }
15431 /*
15432 * SCC "length and minLength or maxLength"
15433 */
15434 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015435 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015436 if (flength) {
15437 if (! fminlen)
15438 flength = bflength;
15439 if (fminlen) {
15440 /* (1.1) length >= minLength */
15441 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15442 if (res == -2)
15443 goto internal_error;
15444 if (res == -1)
15445 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15446 }
15447 if (! fmaxlen)
15448 fmaxlen = bfmaxlen;
15449 if (fmaxlen) {
15450 /* (2.1) length <= maxLength */
15451 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15452 if (res == -2)
15453 goto internal_error;
15454 if (res == 1)
15455 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15456 }
15457 }
15458 if (fmaxinc) {
15459 /*
15460 * "maxInclusive"
15461 */
15462 if (fmininc) {
15463 /* SCC "maxInclusive >= minInclusive" */
15464 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15465 if (res == -2)
15466 goto internal_error;
15467 if (res == -1) {
15468 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15469 }
15470 }
15471 /*
15472 * SCC "maxInclusive valid restriction"
15473 */
15474 if (bfmaxinc) {
15475 /* maxInclusive <= BASE maxInclusive */
15476 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15477 if (res == -2)
15478 goto internal_error;
15479 if (res == 1)
15480 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15481 if ((res != 0) && (bfmaxinc->fixed)) {
15482 FACET_RESTR_FIXED_ERR(fmaxinc)
15483 }
15484 }
15485 if (bfmaxexc) {
15486 /* maxInclusive < BASE maxExclusive */
15487 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15488 if (res == -2)
15489 goto internal_error;
15490 if (res != -1) {
15491 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15492 }
15493 }
15494 if (bfmininc) {
15495 /* maxInclusive >= BASE minInclusive */
15496 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15497 if (res == -2)
15498 goto internal_error;
15499 if (res == -1) {
15500 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15501 }
15502 }
15503 if (bfminexc) {
15504 /* maxInclusive > BASE minExclusive */
15505 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15506 if (res == -2)
15507 goto internal_error;
15508 if (res != 1) {
15509 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15510 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015511 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015512 }
15513 if (fmaxexc) {
15514 /*
15515 * "maxExclusive >= minExclusive"
15516 */
15517 if (fminexc) {
15518 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15519 if (res == -2)
15520 goto internal_error;
15521 if (res == -1) {
15522 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15523 }
15524 }
15525 /*
15526 * "maxExclusive valid restriction"
15527 */
15528 if (bfmaxexc) {
15529 /* maxExclusive <= BASE maxExclusive */
15530 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15531 if (res == -2)
15532 goto internal_error;
15533 if (res == 1) {
15534 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15535 }
15536 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015537 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015538 }
15539 }
15540 if (bfmaxinc) {
15541 /* maxExclusive <= BASE maxInclusive */
15542 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15543 if (res == -2)
15544 goto internal_error;
15545 if (res == 1) {
15546 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15547 }
15548 }
15549 if (bfmininc) {
15550 /* maxExclusive > BASE minInclusive */
15551 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15552 if (res == -2)
15553 goto internal_error;
15554 if (res != 1) {
15555 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15556 }
15557 }
15558 if (bfminexc) {
15559 /* maxExclusive > BASE minExclusive */
15560 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15561 if (res == -2)
15562 goto internal_error;
15563 if (res != 1) {
15564 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15565 }
15566 }
15567 }
15568 if (fminexc) {
15569 /*
15570 * "minExclusive < maxInclusive"
15571 */
15572 if (fmaxinc) {
15573 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15574 if (res == -2)
15575 goto internal_error;
15576 if (res != -1) {
15577 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15578 }
15579 }
15580 /*
15581 * "minExclusive valid restriction"
15582 */
15583 if (bfminexc) {
15584 /* minExclusive >= BASE minExclusive */
15585 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15586 if (res == -2)
15587 goto internal_error;
15588 if (res == -1) {
15589 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15590 }
15591 if ((res != 0) && (bfminexc->fixed)) {
15592 FACET_RESTR_FIXED_ERR(fminexc)
15593 }
15594 }
15595 if (bfmaxinc) {
15596 /* minExclusive <= BASE maxInclusive */
15597 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15598 if (res == -2)
15599 goto internal_error;
15600 if (res == 1) {
15601 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15602 }
15603 }
15604 if (bfmininc) {
15605 /* minExclusive >= BASE minInclusive */
15606 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15607 if (res == -2)
15608 goto internal_error;
15609 if (res == -1) {
15610 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15611 }
15612 }
15613 if (bfmaxexc) {
15614 /* minExclusive < BASE maxExclusive */
15615 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15616 if (res == -2)
15617 goto internal_error;
15618 if (res != -1) {
15619 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15620 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015621 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015622 }
15623 if (fmininc) {
15624 /*
15625 * "minInclusive < maxExclusive"
15626 */
15627 if (fmaxexc) {
15628 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15629 if (res == -2)
15630 goto internal_error;
15631 if (res != -1) {
15632 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15633 }
15634 }
15635 /*
15636 * "minExclusive valid restriction"
15637 */
15638 if (bfmininc) {
15639 /* minInclusive >= BASE minInclusive */
15640 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15641 if (res == -2)
15642 goto internal_error;
15643 if (res == -1) {
15644 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15645 }
15646 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015647 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015648 }
15649 }
15650 if (bfmaxinc) {
15651 /* minInclusive <= BASE maxInclusive */
15652 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15653 if (res == -2)
15654 goto internal_error;
15655 if (res == -1) {
15656 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15657 }
15658 }
15659 if (bfminexc) {
15660 /* minInclusive > BASE minExclusive */
15661 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15662 if (res == -2)
15663 goto internal_error;
15664 if (res != 1)
15665 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15666 }
15667 if (bfmaxexc) {
15668 /* minInclusive < BASE maxExclusive */
15669 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15670 if (res == -2)
15671 goto internal_error;
15672 if (res != -1)
15673 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15674 }
15675 }
15676 if (ftotdig && bftotdig) {
15677 /*
15678 * SCC " totalDigits valid restriction"
15679 * totalDigits <= BASE totalDigits
15680 */
15681 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15682 if (res == -2)
15683 goto internal_error;
15684 if (res == 1)
15685 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15686 -1, 1, 1);
15687 if ((res != 0) && (bftotdig->fixed)) {
15688 FACET_RESTR_FIXED_ERR(ftotdig)
15689 }
15690 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015691 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015692 /*
15693 * SCC "fractionDigits valid restriction"
15694 * fractionDigits <= BASE fractionDigits
15695 */
15696 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15697 if (res == -2)
15698 goto internal_error;
15699 if (res == 1)
15700 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15701 -1, 1, 1);
15702 if ((res != 0) && (bffracdig->fixed)) {
15703 FACET_RESTR_FIXED_ERR(ffracdig)
15704 }
15705 }
15706 /*
15707 * SCC "fractionDigits less than or equal to totalDigits"
15708 */
15709 if (! ftotdig)
15710 ftotdig = bftotdig;
15711 if (! ffracdig)
15712 ffracdig = bffracdig;
15713 if (ftotdig && ffracdig) {
15714 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15715 if (res == -2)
15716 goto internal_error;
15717 if (res == 1)
15718 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15719 -1, 1, 0);
15720 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015721 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015722 * *Enumerations* won' be added here, since only the first set
15723 * of enumerations in the ancestor-or-self axis is used
15724 * for validation, plus we need to use the base type of those
15725 * enumerations for whitespace.
15726 *
15727 * *Patterns*: won't be add here, since they are ORed at
15728 * type level and ANDed at ancestor level. This will
15729 * happed during validation by walking the base axis
15730 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015731 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015732 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15733 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015734 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015735 * Special handling of enumerations and patterns.
15736 * TODO: hmm, they should not appear in the set, so remove this.
15737 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015738 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015739 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015740 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015741 /*
15742 * Search for a duplicate facet in the current type.
15743 */
15744 link = type->facetSet;
15745 err = 0;
15746 fixedErr = 0;
15747 while (link != NULL) {
15748 facet = link->facet;
15749 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015750 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015751 case XML_SCHEMA_FACET_WHITESPACE:
15752 /*
15753 * The whitespace must be stronger.
15754 */
15755 if (facet->whitespace < bfacet->whitespace) {
15756 FACET_RESTR_ERR(flength,
15757 "The 'whitespace' value has to be equal to "
15758 "or stronger than the 'whitespace' value of "
15759 "the base type")
15760 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015761 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015762 (facet->whitespace != bfacet->whitespace)) {
15763 FACET_RESTR_FIXED_ERR(facet)
15764 }
15765 break;
15766 default:
15767 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015768 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015769 /* Duplicate found. */
15770 break;
15771 }
15772 link = link->next;
15773 }
15774 /*
15775 * If no duplicate was found: add the base types's facet
15776 * to the set.
15777 */
15778 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015779 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015780 xmlMalloc(sizeof(xmlSchemaFacetLink));
15781 if (link == NULL) {
15782 xmlSchemaPErrMemory(pctxt,
15783 "deriving facets, creating a facet link", NULL);
15784 return (-1);
15785 }
15786 link->facet = cur->facet;
15787 link->next = NULL;
15788 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015789 type->facetSet = link;
15790 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015791 last->next = link;
15792 last = link;
15793 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015794
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015795 }
15796
15797 return (0);
15798internal_error:
15799 xmlSchemaPCustomErr(pctxt,
15800 XML_SCHEMAP_INVALID_FACET_VALUE,
15801 NULL, type, NULL,
15802 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15803 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015804}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015805
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015806static int
15807xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15808 xmlSchemaTypePtr type)
15809{
15810 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15811 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015812 * The actual value is then formed by replacing any union type
15813 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015814 * {member type definitions}, in order.
15815 */
15816 link = type->memberTypes;
15817 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015818
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015819 if (IS_NOT_TYPEFIXED(link->type))
15820 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15821
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015822 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015823 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015824 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015825 link->type = subLink->type;
15826 if (subLink->next != NULL) {
15827 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015828 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015829 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015830 while (subLink != NULL) {
15831 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015832 xmlMalloc(sizeof(xmlSchemaTypeLink));
15833 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015834 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015835 NULL);
15836 return (-1);
15837 }
15838 newLink->type = subLink->type;
15839 prevLink->next = newLink;
15840 prevLink = newLink;
15841 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015842
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015843 subLink = subLink->next;
15844 }
15845 }
15846 }
15847 }
15848 link = link->next;
15849 }
15850 return (0);
15851}
15852
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015853static void
15854xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15855{
15856 int has = 0, needVal = 0, normVal = 0;
15857
15858 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15859 if (has) {
15860 needVal = (type->baseType->flags &
15861 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15862 normVal = (type->baseType->flags &
15863 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15864 }
15865 if (type->facets != NULL) {
15866 xmlSchemaFacetPtr fac;
15867
15868 for (fac = type->facets; fac != NULL; fac = fac->next) {
15869 switch (fac->type) {
15870 case XML_SCHEMA_FACET_WHITESPACE:
15871 break;
15872 case XML_SCHEMA_FACET_PATTERN:
15873 normVal = 1;
15874 has = 1;
15875 break;
15876 case XML_SCHEMA_FACET_ENUMERATION:
15877 needVal = 1;
15878 normVal = 1;
15879 has = 1;
15880 break;
15881 default:
15882 has = 1;
15883 break;
15884 }
15885 }
15886 }
15887 if (normVal)
15888 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15889 if (needVal)
15890 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15891 if (has)
15892 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15893
15894 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15895 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15896 /*
15897 * OPTIMIZE VAL TODO: Some facets need a computed value.
15898 */
15899 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15900 (prim->builtInType != XML_SCHEMAS_STRING)) {
15901 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15902 }
15903 }
15904}
15905
15906static int
15907xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15908{
15909
15910
15911 /*
15912 * Evaluate the whitespace-facet value.
15913 */
15914 if (VARIETY_LIST(type)) {
15915 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15916 return (0);
15917 } else if (VARIETY_UNION(type))
15918 return (0);
15919
15920 if (type->facetSet != NULL) {
15921 xmlSchemaFacetLinkPtr lin;
15922
15923 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15924 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15925 switch (lin->facet->whitespace) {
15926 case XML_SCHEMAS_FACET_PRESERVE:
15927 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15928 break;
15929 case XML_SCHEMAS_FACET_REPLACE:
15930 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15931 break;
15932 case XML_SCHEMAS_FACET_COLLAPSE:
15933 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15934 break;
15935 default:
15936 return (-1);
15937 }
15938 return (0);
15939 }
15940 }
15941 }
15942 /*
15943 * For all ·atomic· datatypes other than string (and types ·derived·
15944 * by ·restriction· from it) the value of whiteSpace is fixed to
15945 * collapse
15946 */
15947 {
15948 xmlSchemaTypePtr anc;
15949
15950 for (anc = type->baseType; anc != NULL &&
15951 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15952 anc = anc->baseType) {
15953
15954 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15955 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15956 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15957
15958 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15959 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15960 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15961
15962 } else
15963 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15964 break;
15965 }
15966 }
15967 return (0);
15968 }
15969 return (0);
15970}
15971
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015972/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015973 * xmlSchemaTypeFixup:
15974 * @typeDecl: the schema type definition
15975 * @ctxt: the schema parser context
15976 *
15977 * Fixes the content model of the type.
15978 */
15979static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015980xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015981 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015982{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015983 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015984 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015985 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15986 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015987 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015988 if (! IS_NOT_TYPEFIXED(type))
15989 return;
15990 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015991 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015992 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015993
15994 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015995 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015996 XML_SCHEMAP_INTERNAL,
15997 NULL, type, NULL,
15998 "Internal error: xmlSchemaTypeFixup, "
15999 "baseType is missing on '%s'", type->name);
16000 return;
16001 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016002
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016003 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016004 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016005
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016006 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016007 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016008 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016009 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016010 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016011 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16012 /*
16013 * Skip fixup if the base type is invalid.
16014 * TODO: Generate a warning!
16015 */
16016 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016017 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016018 /*
16019 * This basically checks if the base type can be derived.
16020 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016021 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016022 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16023 return;
16024 }
16025 /*
16026 * Fixup the content type.
16027 */
16028 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16029 /*
16030 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016031 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016032 if ((IS_COMPLEX_TYPE(baseType)) &&
16033 (baseType->contentTypeDef != NULL) &&
16034 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016035 xmlSchemaTypePtr contentBase, content;
16036 char buf[30];
16037 const xmlChar *tmpname;
16038 /*
16039 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016040 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016041 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016042 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016043 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016044 * SPEC (1.1) "the simple type definition corresponding to the
16045 * <simpleType> among the [children] of <restriction> if there
16046 * is one;"
16047 * Note that this "<simpleType> among the [children]" was put
16048 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016049 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016050 contentBase = type->contentTypeDef;
16051 type->contentTypeDef = NULL;
16052 } else {
16053 /*
16054 * (1.2) "...otherwise (<restriction> has no <simpleType>
16055 * among its [children]), the simple type definition which
16056 * is the {content type} of the ... base type."
16057 */
16058 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016059 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016060 /*
16061 * SPEC
16062 * "... a simple type definition which restricts the simple
16063 * type definition identified in clause 1.1 or clause 1.2
16064 * with a set of facet components"
16065 *
16066 * Create the anonymous simple type, which will be the content
16067 * type of the complex type.
16068 */
16069 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16070 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16071 content = xmlSchemaAddType(pctxt,
16072 pctxt->schema, tmpname, tmpname, type->node);
16073 if (content == NULL)
16074 return;
16075 /*
16076 * We will use the same node as for the <complexType>
16077 * to have it somehow anchored in the schema doc.
16078 */
16079 content->node = type->node;
16080 content->type = XML_SCHEMA_TYPE_SIMPLE;
16081 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16082 content->baseType = contentBase;
16083 /*
16084 * Move the facets, previously anchored on the complexType.
16085 */
16086 content->facets = type->facets;
16087 type->facets = NULL;
16088 content->facetSet = type->facetSet;
16089 type->facetSet = NULL;
16090
16091 type->contentTypeDef = content;
16092 if (IS_NOT_TYPEFIXED(contentBase))
16093 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16094 xmlSchemaTypeFixup(content, pctxt, NULL);
16095
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016096 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16097 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16098 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16099 /*
16100 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16101 * an emptiable particle, then a simple type definition which
16102 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016103 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016104 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016105 (type->contentTypeDef->baseType == NULL)) {
16106 /*
16107 * TODO: Check if this ever happens.
16108 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016109 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016110 XML_SCHEMAP_INTERNAL,
16111 NULL, type, NULL,
16112 "Internal error: xmlSchemaTypeFixup, "
16113 "complex type '%s': the <simpleContent><restriction> "
16114 "is missing a <simpleType> child, but was not catched "
16115 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016116 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016117 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16118 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16119 /*
16120 * SPEC (3) If <extension> + base is <complexType> with
16121 * <simpleType> content, "...then the {content type} of that
16122 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016123 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016124 if (baseType->contentTypeDef == NULL) {
16125 /*
16126 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16127 * should have catched this already.
16128 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016129 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016130 XML_SCHEMAP_INTERNAL,
16131 NULL, type, NULL,
16132 "Internal error: xmlSchemaTypeFixup, "
16133 "complex type '%s': the <extension>ed base type is "
16134 "a complex type with no simple content type",
16135 type->name);
16136 }
16137 type->contentTypeDef = baseType->contentTypeDef;
16138 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16139 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16140 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016141 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016142 * "... then that simple type definition"
16143 */
16144 type->contentTypeDef = baseType;
16145 } else {
16146 /*
16147 * TODO: Check if this ever happens.
16148 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016149 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016150 XML_SCHEMAP_INTERNAL,
16151 NULL, type, NULL,
16152 "Internal error: xmlSchemaTypeFixup, "
16153 "complex type '%s' with <simpleContent>: unhandled "
16154 "derivation case", type->name);
16155 }
16156 } else {
16157 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016158 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016159 (xmlSchemaParticlePtr) type->subtypes;
16160 /*
16161 * Corresponds to <complexType><complexContent>...
16162 *
16163 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016164 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016165 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016166 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016167 * Compute the "effective content":
16168 * (2.1.1) + (2.1.2) + (2.1.3)
16169 */
16170 if ((particle == NULL) ||
16171 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16172 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16173 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16174 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16175 (particle->minOccurs == 0))) &&
16176 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016177 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016178 /*
16179 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16180 * a particle whose properties are as follows:..."
16181 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016182 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016183 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16184 * NOTE that we sill assign it the <complexType> node to
16185 * somehow anchor it in the doc.
16186 */
16187 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016188 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016189 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016190 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016191 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016192 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016193 type->node, 1, 1);
16194 if (particle == NULL)
16195 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016196 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016197 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016198 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016199 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016200 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016201 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16202 if (particle->children == NULL)
16203 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016204
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016205 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016206 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016207 dummySequence = 1;
16208 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16209 } else {
16210 /*
16211 * SPEC (2.1.5) "otherwise empty"
16212 */
16213 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016214 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016215 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016216 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016217 * SPEC (2.2) "otherwise the particle corresponding to the
16218 * <all>, <choice>, <group> or <sequence> among the
16219 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016220 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016221 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16222 }
16223 /*
16224 * Compute the "content type".
16225 */
16226 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016227 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016228 * SPEC (3.1) "If <restriction>..."
16229 * (3.1.1) + (3.1.2) */
16230 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16231 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16232 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16233 }
16234 } else {
16235 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016236 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016237 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016238 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16239 /*
16240 * SPEC (3.2.1)
16241 */
16242 type->contentType = baseType->contentType;
16243 type->subtypes = baseType->subtypes;
16244 /*
16245 * NOTE that the effective mixed is ignored here.
16246 */
16247 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16248 /*
16249 * SPEC (3.2.2)
16250 */
16251 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16252 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16253 } else {
16254 /*
16255 * SPEC (3.2.3)
16256 */
16257 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16258 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16259 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016260 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016261 * {particles} are..."
16262 */
16263 if (! dummySequence) {
16264 xmlSchemaTreeItemPtr effectiveContent =
16265 (xmlSchemaTreeItemPtr) type->subtypes;
16266 /*
16267 * Create the particle.
16268 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016269 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016270 type->node, 1, 1);
16271 if (particle == NULL)
16272 return;
16273 /*
16274 * Create the "sequence" model group.
16275 */
16276 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016277 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016278 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16279 if (particle->children == NULL)
16280 return;
16281 type->subtypes = (xmlSchemaTypePtr) particle;
16282 /*
16283 * SPEC "the particle of the {content type} of
16284 * the ... base ..."
16285 * Create a duplicate of the base type's particle
16286 * and assign its "term" to it.
16287 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016288 particle->children->children =
16289 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16290 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016291 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016292 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016293 if (particle->children->children == NULL)
16294 return;
16295 particle = (xmlSchemaParticlePtr)
16296 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016297 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016298 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16299 /*
16300 * SPEC "followed by the ·effective content·."
16301 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016302 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016303 } else {
16304 /*
16305 * This is the case when there is already an empty
16306 * <sequence> with minOccurs==maxOccurs==1.
16307 * Just add the base types's content type.
16308 * NOTE that, although we miss to add an intermediate
16309 * <sequence>, this should produce no difference to
16310 * neither the regex compilation of the content model,
16311 * nor to the complex type contraints.
16312 */
16313 particle->children->children =
16314 (xmlSchemaTreeItemPtr) baseType->subtypes;
16315 }
16316 }
16317 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016318 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016319 /*
16320 * Apply the complex type component constraints; this will not
16321 * check attributes, since this is done in
16322 * xmlSchemaBuildAttributeValidation().
16323 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016324 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16325 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016326 /*
16327 * Inherit & check constraints for attributes.
16328 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016329 xmlSchemaBuildAttributeValidation(pctxt, type);
16330 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016331 /*
16332 * Simple Type Definition Schema Component
16333 */
16334 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016335 if (VARIETY_LIST(type)) {
16336 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016337 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016338 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016339 if (type->subtypes == NULL) {
16340 /*
16341 * This one is really needed, so get out.
16342 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016343 PERROR_INT("xmlSchemaTypeFixup",
16344 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016345 return;
16346 }
16347 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016348 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16349 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016350 /*
16351 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016352 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016353 if (type->memberTypes == NULL) {
16354 /*
16355 * This one is really needed, so get out.
16356 */
16357 return;
16358 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016359 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016360 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016361 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016362 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016363 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016364 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016365 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016366 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016367 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16368 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016369 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016370 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016371 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016372 */
16373 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016374 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016375 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16377 /*
16378 * Inherit the itemType.
16379 */
16380 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016381 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016382 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16383 /*
16384 * NOTE that we won't assign the memberTypes of the base,
16385 * since this will make trouble when freeing them; we will
16386 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016387 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016388 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016389 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016390 /*
16391 * Check constraints.
16392 *
16393 * TODO: Split this somehow, we need to know first if we can derive
16394 * from the base type at all!
16395 */
16396 if (type->baseType != NULL) {
16397 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016398 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016399 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016400 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016401 * applied beforehand.
16402 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016403 xmlSchemaCheckSRCSimpleType(pctxt, type);
16404 xmlSchemaCheckFacetValues(type, pctxt);
16405 if ((type->facetSet != NULL) ||
16406 (type->baseType->facetSet != NULL))
16407 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16408 /*
16409 * Whitespace value.
16410 */
16411 xmlSchemaTypeFixupWhitespace(type);
16412 xmlSchemaTypeFixupOptimFacets(type);
16413 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016414 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016415
Daniel Veillard8651f532002-04-17 09:06:27 +000016416#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016417 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016418 xmlGenericError(xmlGenericErrorContext,
16419 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016420 type->node->doc->URL,
16421 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016422 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016423 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016424 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016425 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16426 switch (type->contentType) {
16427 case XML_SCHEMA_CONTENT_SIMPLE:
16428 xmlGenericError(xmlGenericErrorContext, "simple\n");
16429 break;
16430 case XML_SCHEMA_CONTENT_ELEMENTS:
16431 xmlGenericError(xmlGenericErrorContext, "elements\n");
16432 break;
16433 case XML_SCHEMA_CONTENT_UNKNOWN:
16434 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16435 break;
16436 case XML_SCHEMA_CONTENT_EMPTY:
16437 xmlGenericError(xmlGenericErrorContext, "empty\n");
16438 break;
16439 case XML_SCHEMA_CONTENT_MIXED:
16440 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016441 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016442 xmlGenericError(xmlGenericErrorContext,
16443 "mixed as emptiable particle\n");
16444 else
16445 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16446 break;
16447 /* Removed, since not used. */
16448 /*
16449 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16450 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16451 break;
16452 */
16453 case XML_SCHEMA_CONTENT_BASIC:
16454 xmlGenericError(xmlGenericErrorContext, "basic\n");
16455 break;
16456 default:
16457 xmlGenericError(xmlGenericErrorContext,
16458 "not registered !!!\n");
16459 break;
16460 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016461 }
16462#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016463}
16464
16465/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016466 * xmlSchemaCheckFacet:
16467 * @facet: the facet
16468 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016469 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016470 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016471 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016472 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016473 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016474 * Returns 0 if valid, a positive error code if not valid and
16475 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016476 */
16477int
16478xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016479 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016480 xmlSchemaParserCtxtPtr pctxt,
16481 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016482{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016483 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016484
Daniel Veillardce682bc2004-11-05 17:22:25 +000016485 if ((facet == NULL) || (typeDecl == NULL))
16486 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016487 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016488 * TODO: will the parser context be given if used from
16489 * the relaxNG module?
16490 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016491 if (pctxt == NULL)
16492 ctxtGiven = 0;
16493 else
16494 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016495
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016496 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016497 case XML_SCHEMA_FACET_MININCLUSIVE:
16498 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16499 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016500 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16501 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016502 /*
16503 * Okay we need to validate the value
16504 * at that point.
16505 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016506 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016507
16508 /* 4.3.5.5 Constraints on enumeration Schema Components
16509 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016510 * It is an ·error· if any member of {value} is not in the
16511 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016512 *
16513 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016514 * The value ·must· be in the
16515 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016516 */
16517 /*
16518 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016519 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016520 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016521 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016522 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016523 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016524 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016525 */
16526 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16527 base = typeDecl->baseType;
16528 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016529 PERROR_INT("xmlSchemaCheckFacet",
16530 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016531 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016532 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016533 } else
16534 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016535
16536 if (! ctxtGiven) {
16537 /*
16538 * A context is needed if called from RelaxNG.
16539 */
16540 pctxt = xmlSchemaNewParserCtxt("*");
16541 if (pctxt == NULL)
16542 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016543 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016544 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016545 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016546 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016547 * facet->node is just the node holding the facet
16548 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016549 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016550 */
16551 ret = xmlSchemaVCheckCVCSimpleType(
16552 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16553 facet->value, &(facet->val), 1, 1, 0);
16554 if (ret != 0) {
16555 if (ret < 0) {
16556 /* No error message for RelaxNG. */
16557 if (ctxtGiven) {
16558 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16559 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16560 "Internal error: xmlSchemaCheckFacet, "
16561 "failed to validate the value '%s' of the "
16562 "facet '%s' against the base type",
16563 facet->value, xmlSchemaFacetTypeToString(facet->type));
16564 }
16565 goto internal_error;
16566 }
16567 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16568 /* No error message for RelaxNG. */
16569 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016570 xmlChar *str = NULL;
16571
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016572 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16573 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016574 "The value '%s' of the facet does not validate "
16575 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016576 facet->value,
16577 xmlSchemaFormatQName(&str,
16578 base->targetNamespace, base->name));
16579 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016580 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016581 goto exit;
16582 } else if (facet->val == NULL) {
16583 if (ctxtGiven) {
16584 PERROR_INT("xmlSchemaCheckFacet",
16585 "value was not computed");
16586 }
16587 TODO
16588 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016589 break;
16590 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016591 case XML_SCHEMA_FACET_PATTERN:
16592 facet->regexp = xmlRegexpCompile(facet->value);
16593 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016594 ret = XML_SCHEMAP_REGEXP_INVALID;
16595 /* No error message for RelaxNG. */
16596 if (ctxtGiven) {
16597 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16598 ret, facet->node, typeDecl,
16599 "The value '%s' of the facet 'pattern' is not a "
16600 "valid regular expression",
16601 facet->value, NULL);
16602 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016603 }
16604 break;
16605 case XML_SCHEMA_FACET_TOTALDIGITS:
16606 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16607 case XML_SCHEMA_FACET_LENGTH:
16608 case XML_SCHEMA_FACET_MAXLENGTH:
16609 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016610 ret = xmlSchemaValidatePredefinedType(
16611 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16612 facet->value, &(facet->val));
16613 if (ret != 0) {
16614 if (ret < 0) {
16615 /* No error message for RelaxNG. */
16616 if (ctxtGiven) {
16617 PERROR_INT("xmlSchemaCheckFacet",
16618 "validating facet value");
16619 }
16620 goto internal_error;
16621 }
16622 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16623 /* No error message for RelaxNG. */
16624 if (ctxtGiven) {
16625 /* error code */
16626 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16627 ret, facet->node, typeDecl,
16628 "The value '%s' of the facet '%s' is not a valid "
16629 "'nonNegativeInteger'",
16630 facet->value,
16631 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016632 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016633 }
16634 break;
16635 }
16636 case XML_SCHEMA_FACET_WHITESPACE:{
16637 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16638 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16639 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16640 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16641 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16642 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16643 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016644 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16645 /* No error message for RelaxNG. */
16646 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016647 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016648 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16649 ret, facet->node, typeDecl,
16650 "The value '%s' of the facet 'whitespace' is not "
16651 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016652 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016653 }
16654 }
16655 default:
16656 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016657 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016658exit:
16659 if ((! ctxtGiven) && (pctxt != NULL))
16660 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016661 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016662internal_error:
16663 if ((! ctxtGiven) && (pctxt != NULL))
16664 xmlSchemaFreeParserCtxt(pctxt);
16665 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016666}
16667
16668/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016669 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016670 * @typeDecl: the schema type definition
16671 * @ctxt: the schema parser context
16672 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016673 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016674 */
16675static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016676xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16677 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016678{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016679 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016680 /*
16681 * NOTE: It is intended to use the facets list, instead
16682 * of facetSet.
16683 */
16684 if (typeDecl->facets != NULL) {
16685 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016686
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016687 /*
16688 * Temporarily assign the "schema" to the validation context
16689 * of the parser context. This is needed for NOTATION validation.
16690 */
16691 if (ctxt->vctxt == NULL) {
16692 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16693 return;
16694 }
16695 ctxt->vctxt->schema = ctxt->schema;
16696
Daniel Veillard01fa6152004-06-29 17:04:39 +000016697 while (facet != NULL) {
16698 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16699 facet = facet->next;
16700 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016701
16702 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016703 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016704}
16705
16706/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016707 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016708 * @ctxtMGroup: the searched model group
16709 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016710 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016711 *
16712 * This one is intended to be used by
16713 * xmlSchemaCheckGroupDefCircular only.
16714 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016715 * Returns the particle with the circular model group definition reference,
16716 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016717 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016718static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016719xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016720 xmlSchemaTreeItemPtr particle)
16721{
16722 xmlSchemaTreeItemPtr circ = NULL;
16723 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016724 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016725
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016726 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016727 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016728 if (term == NULL)
16729 continue;
16730 switch (term->type) {
16731 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016732 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016733 if (gdef == groupDef)
16734 return (particle);
16735 /*
16736 * Mark this model group definition to avoid infinite
16737 * recursion on circular references not yet examined.
16738 */
16739 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16740 continue;
16741 if (gdef->children != NULL) {
16742 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16743 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16744 gdef->children->children);
16745 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16746 if (circ != NULL)
16747 return (circ);
16748 }
16749 break;
16750 case XML_SCHEMA_TYPE_SEQUENCE:
16751 case XML_SCHEMA_TYPE_CHOICE:
16752 case XML_SCHEMA_TYPE_ALL:
16753 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16754 if (circ != NULL)
16755 return (circ);
16756 break;
16757 default:
16758 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016759 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016760 }
16761 return (NULL);
16762}
16763
16764/**
16765 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016766 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016767 * @ctxt: the parser context
16768 * @name: the name
16769 *
16770 * Checks for circular references to model group definitions.
16771 */
16772static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016773xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016774 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016775 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016776{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016777 /*
16778 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016779 * 2 Circular groups are disallowed. That is, within the {particles}
16780 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016781 * is the group itself.
16782 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016783 if ((item == NULL) ||
16784 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16785 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016786 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016787 {
16788 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016789
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016790 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016791 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016792 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016793 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016794 * TODO: The error report is not adequate: this constraint
16795 * is defined for model groups but not definitions, but since
16796 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016797 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016798 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016799 */
16800 xmlSchemaPCustomErr(ctxt,
16801 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016802 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016803 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016804 "defined", xmlSchemaFormatQName(&str,
16805 item->targetNamespace, item->name));
16806 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016807 /*
16808 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016809 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016810 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016811 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016812 }
16813 }
16814}
16815
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016816/**
16817 * xmlSchemaGroupDefTermFixup:
16818 * @item: the particle with a model group definition as term
16819 * @ctxt: the parser context
16820 * @name: the name
16821 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016822 * Checks cos-all-limited.
16823 *
16824 * Assigns the model group of model group definitions to the "term"
16825 * of the referencing particle.
16826 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16827 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016828 */
16829static void
16830xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016831 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016832 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016833{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016834 if ((item == NULL) ||
16835 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16836 (item->children == NULL) ||
16837 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16838 (item->children->children == NULL))
16839 return;
16840 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016841 /*
16842 * TODO: Not nice, but we will anchor cos-all-limited here.
16843 */
16844 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16845 (item->maxOccurs != 1)) {
16846 /*
16847 * SPEC (1.2) "the {term} property of a particle with
16848 * {max occurs}=1which is part of a pair which constitutes the
16849 * {content type} of a complex type definition."
16850 */
16851 xmlSchemaPCustomErr(ctxt,
16852 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16853 NULL, (xmlSchemaTypePtr) item, item->node,
16854 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16855 "group is its term", NULL);
16856 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016857}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016858
16859/**
16860 * xmlSchemaGetCircAttrGrRef:
16861 * @ctxtGr: the searched attribute group
16862 * @attr: the current attribute list to be processed
16863 *
16864 * This one is intended to be used by
16865 * xmlSchemaCheckSRCAttributeGroupCircular only.
16866 *
16867 * Returns the circular attribute grou reference, otherwise NULL.
16868 */
16869static xmlSchemaAttributeGroupPtr
16870xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16871 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016872{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016873 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16874 int marked;
16875 /*
16876 * We will search for an attribute group reference which
16877 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016878 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016879 while (attr != NULL) {
16880 marked = 0;
16881 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16882 gr = (xmlSchemaAttributeGroupPtr) attr;
16883 if (gr->refItem != NULL) {
16884 if (gr->refItem == ctxtGr)
16885 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016886 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016887 XML_SCHEMAS_ATTRGROUP_MARKED) {
16888 attr = attr->next;
16889 continue;
16890 } else {
16891 /*
16892 * Mark as visited to avoid infinite recursion on
16893 * circular references not yet examined.
16894 */
16895 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16896 marked = 1;
16897 }
16898 }
16899 if (gr->attributes != NULL)
16900 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16901 /*
16902 * Unmark the visited group's attributes.
16903 */
16904 if (marked)
16905 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16906 if (circ != NULL)
16907 return (circ);
16908 }
16909 attr = attr->next;
16910 }
16911 return (NULL);
16912}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016913
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016914/**
16915 * xmlSchemaCheckSRCAttributeGroupCircular:
16916 * attrGr: the attribute group definition
16917 * @ctxt: the parser context
16918 * @name: the name
16919 *
16920 * Checks for circular references of attribute groups.
16921 */
16922static void
16923xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016924 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016925 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016926{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016927 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016928 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016929 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016930 * 3 Circular group reference is disallowed outside <redefine>.
16931 * That is, unless this element information item's parent is
16932 * <redefine>, then among the [children], if any, there must
16933 * not be an <attributeGroup> with ref [attribute] which resolves
16934 * to the component corresponding to this <attributeGroup>. Indirect
16935 * circularity is also ruled out. That is, when QName resolution
16936 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16937 * any <attributeGroup>s with a ref [attribute] among the [children],
16938 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016939 * which resolves to the component corresponding to this <attributeGroup>.
16940 */
16941 /*
16942 * Only global components can be referenced.
16943 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016944 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016945 (attrGr->attributes == NULL))
16946 return;
16947 else {
16948 xmlSchemaAttributeGroupPtr circ;
16949
16950 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16951 if (circ != NULL) {
16952 /*
16953 * TODO: Report the referenced attr group as QName.
16954 */
16955 xmlSchemaPCustomErr(ctxt,
16956 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16957 NULL, NULL, circ->node,
16958 "Circular reference to the attribute group '%s' "
16959 "defined", attrGr->name);
16960 /*
16961 * NOTE: We will cut the reference to avoid further
16962 * confusion of the processor.
16963 * BADSPEC: The spec should define how to process in this case.
16964 */
16965 circ->attributes = NULL;
16966 circ->refItem = NULL;
16967 }
16968 }
16969}
16970
16971/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016972 * xmlSchemaAttrGrpFixup:
16973 * @attrgrpDecl: the schema attribute definition
16974 * @ctxt: the schema parser context
16975 * @name: the attribute name
16976 *
16977 * Fixes finish doing the computations on the attributes definitions
16978 */
16979static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016980xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016981 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016982{
16983 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016984 name = attrgrp->name;
16985 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016986 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016987 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016988 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016989
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016990 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016991 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016992 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016993 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016994 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016995 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16996 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016997 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016998 return;
16999 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017000 attrgrp->refItem = ref;
17001 /*
17002 * Check for self reference!
17003 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017004 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017005 attrgrp->attributes = ref->attributes;
17006 attrgrp->attributeWildcard = ref->attributeWildcard;
17007 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017008}
17009
17010/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017011 * xmlSchemaAttrCheckValConstr:
17012 * @item: an schema attribute declaration/use
17013 * @ctxt: a schema parser context
17014 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017015 *
17016 *
17017 * Schema Component Constraint: Attribute Declaration Properties Correct
17018 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017019 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017020 *
17021 * Fixes finish doing the computations on the attributes definitions
17022 */
17023static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017024xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017025 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017026 const xmlChar * name ATTRIBUTE_UNUSED)
17027{
17028
17029 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017030 * 2 if there is a {value constraint}, the canonical lexical
17031 * representation of its value must be ·valid· with respect
17032 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017033 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017034 if (item->defValue != NULL) {
17035 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017036
17037 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017038 PERROR_INT("xmlSchemaCheckAttrValConstr",
17039 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017040 return;
17041 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017042 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17043 item->node, item->subtypes, item->defValue, &(item->defVal),
17044 1, 1, 0);
17045 if (ret != 0) {
17046 if (ret < 0) {
17047 PERROR_INT("xmlSchemaAttrCheckValConstr",
17048 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017049 return;
17050 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017051 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17052 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17053 ret, item->node, (xmlSchemaTypePtr) item,
17054 "The value of the value constraint is not valid", NULL, NULL);
17055 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017056 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017057 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017058}
17059
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017060static xmlSchemaElementPtr
17061xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17062 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017063{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017064 xmlSchemaElementPtr ret;
17065
17066 if (SUBST_GROUP_AFF(ancestor) == NULL)
17067 return (NULL);
17068 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17069 return (ancestor);
17070
17071 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17072 return (NULL);
17073 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17074 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17075 SUBST_GROUP_AFF(ancestor));
17076 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17077
17078 return (ret);
17079}
17080
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017081/**
17082 * xmlSchemaCheckElemPropsCorrect:
17083 * @ctxt: a schema parser context
17084 * @decl: the element declaration
17085 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017086 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017087 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017088 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017089 *
17090 * STATUS:
17091 * missing: (6)
17092 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017093static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017094xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17095 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017096{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017097 int ret = 0;
17098 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017099 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017100 * SPEC (1) "The values of the properties of an element declaration
17101 * must be as described in the property tableau in The Element
17102 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17103 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017104 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017105 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017106 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017107
17108 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017109 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017110 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017111 * affiliation}, then {scope} must be global."
17112 */
17113 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17114 xmlSchemaPCustomErr(pctxt,
17115 XML_SCHEMAP_E_PROPS_CORRECT_3,
17116 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17117 "Only global element declarations can have a "
17118 "substitution group affiliation", NULL);
17119 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017120 }
17121 /*
17122 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17123 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017124 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017125 * property."
17126 */
17127 if (head == elemDecl)
17128 circ = head;
17129 else if (SUBST_GROUP_AFF(head) != NULL)
17130 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17131 else
17132 circ = NULL;
17133 if (circ != NULL) {
17134 xmlChar *strA = NULL, *strB = NULL;
17135
17136 xmlSchemaPCustomErrExt(pctxt,
17137 XML_SCHEMAP_E_PROPS_CORRECT_6,
17138 NULL, (xmlSchemaTypePtr) circ, circ->node,
17139 "The element declaration '%s' defines a circular "
17140 "substitution group to element declaration '%s'",
17141 xmlSchemaGetComponentQName(&strA, circ),
17142 xmlSchemaGetComponentQName(&strB, head),
17143 NULL);
17144 FREE_AND_NULL(strA)
17145 FREE_AND_NULL(strB)
17146 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17147 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017148 /*
17149 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017150 * the {type definition}
17151 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017152 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017153 * of the {substitution group exclusions} of the {substitution group
17154 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17155 * (if the {type definition} is complex) or as defined in
17156 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017157 * simple)."
17158 *
17159 * NOTE: {substitution group exclusions} means the values of the
17160 * attribute "final".
17161 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017162
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017163 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017164 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017165
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017166 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17167 set |= SUBSET_EXTENSION;
17168 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17169 set |= SUBSET_RESTRICTION;
17170
17171 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17172 ELEM_TYPE(head), set) != 0) {
17173 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17174
17175 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017176 xmlSchemaPCustomErrExt(pctxt,
17177 XML_SCHEMAP_E_PROPS_CORRECT_4,
17178 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017179 "The type definition '%s' was "
17180 "either rejected by the substitution group "
17181 "affiliation '%s', or not validly derived from its type "
17182 "definition '%s'",
17183 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017184 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017185 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017186 FREE_AND_NULL(strA)
17187 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017188 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017189 }
17190 }
17191 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017192 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017193 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017194 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017195 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017196 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017197 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017198 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017199 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017200 ((IS_SIMPLE_TYPE(typeDef) &&
17201 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017202 (IS_COMPLEX_TYPE(typeDef) &&
17203 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017204 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17205 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017206
17207 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17208 xmlSchemaPCustomErr(pctxt,
17209 XML_SCHEMAP_E_PROPS_CORRECT_5,
17210 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17211 "The type definition (or type definition's content type) is or "
17212 "is derived from ID; value constraints are not allowed in "
17213 "conjunction with such a type definition", NULL);
17214 } else if (elemDecl->value != NULL) {
17215 int vcret;
17216 xmlNodePtr node = NULL;
17217
17218 /*
17219 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17220 * representation of its value must be ·valid· with respect to the
17221 * {type definition} as defined in Element Default Valid (Immediate)
17222 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017223 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017224 if (typeDef == NULL) {
17225 xmlSchemaPErr(pctxt, elemDecl->node,
17226 XML_SCHEMAP_INTERNAL,
17227 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17228 "type is missing... skipping validation of "
17229 "the value constraint", NULL, NULL);
17230 return (-1);
17231 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017232 if (elemDecl->node != NULL) {
17233 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17234 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17235 BAD_CAST "fixed");
17236 else
17237 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17238 BAD_CAST "default");
17239 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017240 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17241 typeDef, elemDecl->value, &(elemDecl->defVal));
17242 if (vcret != 0) {
17243 if (vcret < 0) {
17244 PERROR_INT("xmlSchemaElemCheckValConstr",
17245 "failed to validate the value constraint of an "
17246 "element declaration");
17247 return (-1);
17248 }
17249 return (vcret);
17250 }
17251 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017252
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017253 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017254}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017255
17256/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017257 * xmlSchemaCheckElemSubstGroup:
17258 * @ctxt: a schema parser context
17259 * @decl: the element declaration
17260 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017261 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017262 * Schema Component Constraint:
17263 * Substitution Group (cos-equiv-class)
17264 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017265 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017266 * a list will be built for each subst. group head, holding all direct
17267 * referents to this head.
17268 * NOTE that this function needs:
17269 * 1. circular subst. groups to be checked beforehand
17270 * 2. the declaration's type to be derived from the head's type
17271 *
17272 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017273 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017274 */
17275static void
17276xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17277 xmlSchemaElementPtr elemDecl)
17278{
17279 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17280 /* SPEC (1) "Its {abstract} is false." */
17281 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17282 return;
17283 {
17284 xmlSchemaElementPtr head;
17285 xmlSchemaTypePtr headType, type;
17286 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017287 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017288 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17289 * {disallowed substitutions} as the blocking constraint, as defined in
17290 * Substitution Group OK (Transitive) (§3.3.6)."
17291 */
17292 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17293 head = SUBST_GROUP_AFF(head)) {
17294 set = 0;
17295 methSet = 0;
17296 /*
17297 * The blocking constraints.
17298 */
17299 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17300 continue;
17301 headType = head->subtypes;
17302 type = elemDecl->subtypes;
17303 if (headType == type)
17304 goto add_member;
17305 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17306 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17307 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17308 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17309 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017310 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017311 * "The set of all {derivation method}s involved in the
17312 * derivation of D's {type definition} from C's {type definition}
17313 * does not intersect with the union of the blocking constraint,
17314 * C's {prohibited substitutions} (if C is complex, otherwise the
17315 * empty set) and the {prohibited substitutions} (respectively the
17316 * empty set) of any intermediate {type definition}s in the
17317 * derivation of D's {type definition} from C's {type definition}."
17318 */
17319 /*
17320 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17321 * subst.head axis, the methSet does not need to be computed for
17322 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017323 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017324 /*
17325 * The set of all {derivation method}s involved in the derivation
17326 */
17327 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017328 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017329 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17330 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17331 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017332
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017333 if ((type->flags &
17334 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17335 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17336 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17337
17338 type = type->baseType;
17339 }
17340 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017341 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017342 * the head's type.
17343 */
17344 type = elemDecl->subtypes->baseType;
17345 while (type != NULL) {
17346 if (IS_COMPLEX_TYPE(type)) {
17347 if ((type->flags &
17348 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17349 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17350 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17351 if ((type->flags &
17352 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17353 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17354 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17355 } else
17356 break;
17357 if (type == headType)
17358 break;
17359 type = type->baseType;
17360 }
17361 if ((set != 0) &&
17362 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17363 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17364 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17365 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17366 continue;
17367 }
17368add_member:
17369 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17370 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17371 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17372 }
17373 }
17374}
17375
17376/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017377 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017378 * @item: an schema element declaration/particle
17379 * @ctxt: a schema parser context
17380 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017381 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017382 * Validates the value constraints of an element declaration.
17383 *
17384 * Fixes finish doing the computations on the element declarations.
17385 */
17386static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017387xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017388 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017389 const xmlChar * name ATTRIBUTE_UNUSED)
17390{
17391 if (elemDecl == NULL)
17392 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017393 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17394 return;
17395 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017396 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17397 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017398}
17399
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017400/**
17401 * xmlSchemaMiscRefFixup:
17402 * @item: an schema component
17403 * @ctxt: a schema parser context
17404 * @name: the internal name of the component
17405 *
17406 * Resolves references of misc. schema components.
17407 */
17408static void
17409xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017410 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017411 const xmlChar * name ATTRIBUTE_UNUSED)
17412{
17413 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017414 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017415 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17416 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17417 xmlSchemaTreeItemPtr refItem;
17418 /*
17419 * Resolve the reference.
17420 */
17421 item->children = NULL;
17422 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17423 ref->itemType, ref->name, ref->targetNamespace);
17424 if (refItem == NULL) {
17425 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017426 NULL, GET_NODE(item), "ref", ref->name,
17427 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017428 } else {
17429 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17430 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017431 * NOTE that we will assign the model group definition
17432 * itself to the "term" of the particle. This will ease
17433 * the check for circular model group definitions. After
17434 * that the "term" will be assigned the model group of the
17435 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017436 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017437 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017438 } else
17439 item->children = refItem;
17440 }
17441 }
17442 }
17443}
17444
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017445static int
17446xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17447 xmlSchemaValPtr y)
17448{
17449 xmlSchemaTypePtr tx, ty, ptx, pty;
17450 int ret;
17451
17452 while (x != NULL) {
17453 /* Same types. */
17454 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17455 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17456 ptx = xmlSchemaGetPrimitiveType(tx);
17457 pty = xmlSchemaGetPrimitiveType(ty);
17458 /*
17459 * (1) if a datatype T' is ·derived· by ·restriction· from an
17460 * atomic datatype T then the ·value space· of T' is a subset of
17461 * the ·value space· of T. */
17462 /*
17463 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17464 * from a common atomic ancestor T then the ·value space·s of T'
17465 * and T'' may overlap.
17466 */
17467 if (ptx != pty)
17468 return(0);
17469 /*
17470 * We assume computed values to be normalized, so do a fast
17471 * string comparison for string based types.
17472 */
17473 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17474 IS_ANY_SIMPLE_TYPE(ptx)) {
17475 if (! xmlStrEqual(
17476 xmlSchemaValueGetAsString(x),
17477 xmlSchemaValueGetAsString(y)))
17478 return (0);
17479 } else {
17480 ret = xmlSchemaCompareValuesWhtsp(
17481 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17482 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17483 if (ret == -2)
17484 return(-1);
17485 if (ret != 0)
17486 return(0);
17487 }
17488 /*
17489 * Lists.
17490 */
17491 x = xmlSchemaValueGetNext(x);
17492 if (x != NULL) {
17493 y = xmlSchemaValueGetNext(y);
17494 if (y == NULL)
17495 return (0);
17496 } else if (xmlSchemaValueGetNext(y) != NULL)
17497 return (0);
17498 else
17499 return (1);
17500 }
17501 return (0);
17502}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017503
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017504/**
17505 * xmlSchemaAttrFixup:
17506 * @item: an schema attribute declaration/use.
17507 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017508 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017509 *
17510 * Fixes finish doing the computations on attribute declarations/uses.
17511 */
17512static void
17513xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017514 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017515 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017516{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017517 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017518 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017519 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017520 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017521 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017522 * The simple type definition corresponding to the <simpleType> element
17523 * information item in the [children], if present, otherwise the simple
17524 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017525 * [attribute], if present, otherwise the ·simple ur-type definition·.
17526 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017527 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017528 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017529 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17530 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017531 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017532 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017533 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017534
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017535 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17536 item->typeNs);
17537 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017538 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017539 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017540 (xmlSchemaTypePtr) item, item->node,
17541 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017542 XML_SCHEMA_TYPE_SIMPLE, NULL);
17543 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017544 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017545
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017546 } else if (item->ref != NULL) {
17547 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017548
Daniel Veillardc0826a72004-08-10 14:17:33 +000017549 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017550 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017551 * attribute declaration.
17552 */
17553 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017554 * TODO: Evaluate, what errors could occur if the declaration is not
17555 * found. It might be possible that the "typefixup" might crash if
17556 * no ref declaration was found.
17557 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017558 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017559 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017560 xmlSchemaPResCompAttrErr(ctxt,
17561 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017562 (xmlSchemaTypePtr) item, item->node,
17563 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017564 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017565 return;
17566 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017567 item->refDecl = decl;
17568 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017569 item->subtypes = decl->subtypes;
17570 /*
17571 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017572 * au-props-correct.2: If the {attribute declaration} has a fixed
17573 * {value constraint}, then if the attribute use itself has a
17574 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017575 * that of the {attribute declaration}'s {value constraint}.
17576 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017577 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017578 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017579 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017580 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017581 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17582 NULL, NULL, item->node,
17583 "The attribute declaration has a 'fixed' value constraint "
17584 ", thus it must be 'fixed' in attribute use as well",
17585 NULL);
17586 } else {
17587 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17588 xmlSchemaPCustomErr(ctxt,
17589 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17590 NULL, NULL, item->node,
17591 "The 'fixed' value constraint of the attribute use "
17592 "must match the attribute declaration's value "
17593 "constraint '%s'",
17594 decl->defValue);
17595 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017596 }
17597 /*
17598 * FUTURE: One should change the values of the attr. use
17599 * if ever validation should be attempted even if the
17600 * schema itself was not fully valid.
17601 */
17602 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017603 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017604 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17605 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017606}
17607
17608/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017609 * xmlSchemaResolveIDCKeyRef:
17610 * @idc: the identity-constraint definition
17611 * @ctxt: the schema parser context
17612 * @name: the attribute name
17613 *
17614 * Resolve keyRef references to key/unique IDCs.
17615 */
17616static void
17617xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017618 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017619 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017620{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017621 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17622 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017623 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017624 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017625 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017626 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017627 idc->ref->targetNamespace);
17628 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017629 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017630 * TODO: It is actually not an error to fail to resolve.
17631 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017632 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017633 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017634 (xmlSchemaTypePtr) idc, idc->node,
17635 "refer", idc->ref->name,
17636 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017637 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17638 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017639 } else {
17640 if (idc->nbFields !=
17641 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17642 xmlChar *str = NULL;
17643 xmlSchemaIDCPtr refer;
17644
17645 refer = (xmlSchemaIDCPtr) idc->ref->item;
17646 /*
17647 * SPEC c-props-correct(2)
17648 * "If the {identity-constraint category} is keyref,
17649 * the cardinality of the {fields} must equal that of
17650 * the {fields} of the {referenced key}.
17651 */
17652 xmlSchemaPCustomErr(pctxt,
17653 XML_SCHEMAP_C_PROPS_CORRECT,
17654 NULL, (xmlSchemaTypePtr) idc, idc->node,
17655 "The cardinality of the keyref differs from the "
17656 "cardinality of the referenced key '%s'",
17657 xmlSchemaFormatQName(&str, refer->targetNamespace,
17658 refer->name)
17659 );
17660 FREE_AND_NULL(str)
17661 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017662 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017663 }
17664}
17665
17666/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017667 * xmlSchemaParse:
17668 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017669 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017670 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017671 * XML Shema struture which can be used to validate instances.
17672 * *WARNING* this interface is highly subject to change
17673 *
17674 * Returns the internal XML Schema structure built from the resource or
17675 * NULL in case of error
17676 */
17677xmlSchemaPtr
17678xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17679{
17680 xmlSchemaPtr ret = NULL;
17681 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017682 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017683 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017684
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017685 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017686 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017687 * the API; i.e. not automatically by the validated instance document.
17688 */
17689
Daniel Veillard4255d502002-04-16 15:50:10 +000017690 xmlSchemaInitTypes();
17691
Daniel Veillard6045c902002-10-09 21:13:59 +000017692 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017693 return (NULL);
17694
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017695 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017696 ctxt->counter = 0;
17697 ctxt->container = NULL;
17698
17699 /*
17700 * First step is to parse the input document into an DOM/Infoset
17701 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017702 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017703 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017704 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017705 if (doc == NULL) {
17706 xmlSchemaPErr(ctxt, NULL,
17707 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017708 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017709 ctxt->URL, NULL);
17710 return (NULL);
17711 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017712 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017713 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17714 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017715 if (doc == NULL) {
17716 xmlSchemaPErr(ctxt, NULL,
17717 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017718 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017719 NULL, NULL);
17720 return (NULL);
17721 }
17722 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017723 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017724 } else if (ctxt->doc != NULL) {
17725 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017726 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017727 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017728 xmlSchemaPErr(ctxt, NULL,
17729 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017730 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017731 NULL, NULL);
17732 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017733 }
17734
17735 /*
17736 * Then extract the root and Schema parse it
17737 */
17738 root = xmlDocGetRootElement(doc);
17739 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017740 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17741 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017742 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017743 if (!preserve) {
17744 xmlFreeDoc(doc);
17745 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017746 return (NULL);
17747 }
17748
17749 /*
17750 * Remove all the blank text nodes
17751 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017752 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017753
17754 /*
17755 * Then do the parsing for good
17756 */
17757 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017758 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017759 if (!preserve) {
17760 xmlFreeDoc(doc);
17761 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017762 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017763 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017764 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017765 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017766 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017767 ctxt->ctxtType = NULL;
17768 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017769
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017770 /*
17771 * Resolve base types of simple/complex types.
17772 */
17773 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017774
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017775 if (ctxt->nberrors != 0)
17776 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017777
17778 if (ret->volatiles != NULL) {
17779 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17780 int i;
17781 xmlSchemaTreeItemPtr item;
17782
17783 for (i = 0; i < list->nbItems; i++) {
17784 item = (xmlSchemaTreeItemPtr) list->items[i];
17785 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17786 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017787 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017788 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017789 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017790 * Then fixup all attributes declarations
17791 */
17792 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017793 /*
17794 * Then fixup all attributes group declarations
17795 */
17796 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17797 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017798 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017799 * Resolve identity-constraint keyRefs.
17800 */
17801 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017802 /*
17803 * Check type defnitions for circular references.
17804 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017805 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017806 xmlSchemaCheckTypeDefCircular, ctxt);
17807 /*
17808 * Check model groups defnitions for circular references.
17809 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017810 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017811 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017812 /*
17813 * Set the "term" of particles pointing to model group definitions
17814 * to the contained model group.
17815 */
17816 if (ret->volatiles != NULL) {
17817 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17818 int i;
17819 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017820
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017821 for (i = 0; i < list->nbItems; i++) {
17822 item = (xmlSchemaParticlePtr) list->items[i];
17823 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17824 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17825 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017826 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017827 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017828 * Check attribute groups for circular references.
17829 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017830 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17831 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017832 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017833 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017834 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017835 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017836 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017837 /*
17838 * We will stop here if the schema was not valid to avoid internal errors
17839 * on missing sub-components. This is not conforming to the spec, since it
17840 * allows missing components, but it might make further processing crash.
17841 * So see it as a very strict handling, which might be made more lax in the
17842 * future.
17843 */
17844 if (ctxt->nberrors != 0)
17845 goto exit;
17846 /*
17847 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017848 */
17849 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017850 /*
17851 * Validate the value constraint of attribute declarations/uses.
17852 */
17853 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017854 /*
17855 * Validate the value constraint of element declarations.
17856 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017857 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017858
17859 if (ctxt->nberrors != 0)
17860 goto exit;
17861
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017862 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017863 * TODO: cos-element-consistent, cos-all-limited
17864 *
17865 * Then build the content model for all complex types
17866 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017867 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017868 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017869
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017870exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017871 if (ctxt->nberrors != 0) {
17872 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017873 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017874 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017875 return (ret);
17876}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017877
Daniel Veillard4255d502002-04-16 15:50:10 +000017878/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017879 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017880 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017881 * @err: the error callback
17882 * @warn: the warning callback
17883 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017884 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017885 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017886 */
17887void
17888xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017889 xmlSchemaValidityErrorFunc err,
17890 xmlSchemaValidityWarningFunc warn, void *ctx)
17891{
Daniel Veillard4255d502002-04-16 15:50:10 +000017892 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017893 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017894 ctxt->error = err;
17895 ctxt->warning = warn;
17896 ctxt->userData = ctx;
17897}
17898
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017899/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017900 * xmlSchemaGetParserErrors:
17901 * @ctxt: a XMl-Schema parser context
17902 * @err: the error callback result
17903 * @warn: the warning callback result
17904 * @ctx: contextual data for the callbacks result
17905 *
17906 * Get the callback information used to handle errors for a parser context
17907 *
17908 * Returns -1 in case of failure, 0 otherwise
17909 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017910int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017911xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17912 xmlSchemaValidityErrorFunc * err,
17913 xmlSchemaValidityWarningFunc * warn, void **ctx)
17914{
17915 if (ctxt == NULL)
17916 return(-1);
17917 if (err != NULL)
17918 *err = ctxt->error;
17919 if (warn != NULL)
17920 *warn = ctxt->warning;
17921 if (ctx != NULL)
17922 *ctx = ctxt->userData;
17923 return(0);
17924}
17925
17926/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017927 * xmlSchemaFacetTypeToString:
17928 * @type: the facet type
17929 *
17930 * Convert the xmlSchemaTypeType to a char string.
17931 *
17932 * Returns the char string representation of the facet type if the
17933 * type is a facet and an "Internal Error" string otherwise.
17934 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017935static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017936xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17937{
17938 switch (type) {
17939 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017940 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017941 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017942 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017943 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017944 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017945 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017946 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017947 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017948 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017949 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017950 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017951 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017952 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017953 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017954 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017955 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017956 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017957 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017958 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017959 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017960 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017961 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017962 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017963 default:
17964 break;
17965 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017966 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017967}
17968
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017969static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017970xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17971{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017972 /*
17973 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017974 * from xsd:string.
17975 */
17976 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017977 /*
17978 * Note that we assume a whitespace of preserve for anySimpleType.
17979 */
17980 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17981 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17982 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017983 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017984 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017985 else {
17986 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017987 * For all ·atomic· datatypes other than string (and types ·derived·
17988 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000017989 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017990 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017991 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017992 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017993 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017994 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017995 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017996 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017997 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017998 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
17999 } else if (VARIETY_UNION(type)) {
18000 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
18001 } else if (VARIETY_ATOMIC(type)) {
18002 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
18003 return (XML_SCHEMA_WHITESPACE_PRESERVE);
18004 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
18005 return (XML_SCHEMA_WHITESPACE_REPLACE);
18006 else
18007 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018008 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018009 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018010}
18011
Daniel Veillard4255d502002-04-16 15:50:10 +000018012/************************************************************************
18013 * *
18014 * Simple type validation *
18015 * *
18016 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018017
Daniel Veillard4255d502002-04-16 15:50:10 +000018018
18019/************************************************************************
18020 * *
18021 * DOM Validation code *
18022 * *
18023 ************************************************************************/
18024
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018025static void
18026xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18027{
18028 int i, nbItems;
18029 xmlSchemaTypePtr item, *items;
18030
18031
18032 /*
18033 * During the Assemble of the schema ctxt->curItems has
18034 * been filled with the relevant new items. Fix those up.
18035 */
18036 nbItems = ctxt->assemble->nbItems;
18037 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018038
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018039 for (i = 0; i < nbItems; i++) {
18040 item = items[i];
18041 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018042 case XML_SCHEMA_TYPE_COMPLEX:
18043 case XML_SCHEMA_TYPE_SIMPLE:
18044 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18045 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018046 case XML_SCHEMA_TYPE_ATTRIBUTE:
18047 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18048 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018049 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018050 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018051 ctxt, NULL);
18052 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018053 case XML_SCHEMA_TYPE_PARTICLE:
18054 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018055 break;
18056 case XML_SCHEMA_TYPE_IDC_KEY:
18057 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18058 case XML_SCHEMA_TYPE_IDC_KEYREF:
18059 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18060 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018061 default:
18062 break;
18063 }
18064 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018065 if (ctxt->nberrors != 0)
18066 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018067 /*
18068 * Circularity checks.
18069 */
18070 for (i = 0; i < nbItems; i++) {
18071 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018072 switch (item->type) {
18073 case XML_SCHEMA_TYPE_COMPLEX:
18074 case XML_SCHEMA_TYPE_SIMPLE:
18075 xmlSchemaCheckTypeDefCircular(
18076 (xmlSchemaTypePtr) item, ctxt, NULL);
18077 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018078 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018079 xmlSchemaCheckGroupDefCircular(
18080 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018081 break;
18082 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18083 xmlSchemaCheckAttributeGroupCircular(
18084 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18085 break;
18086 default:
18087 break;
18088 }
18089 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018090 if (ctxt->nberrors != 0)
18091 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018092 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018093 * Set the "term" of particles pointing to model group definitions
18094 * to the contained model group.
18095 */
18096 for (i = 0; i < nbItems; i++) {
18097 item = items[i];
18098 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18099 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018100 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018101 XML_SCHEMA_TYPE_GROUP)) {
18102 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18103 ctxt, NULL);
18104 }
18105 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018106 if (ctxt->nberrors != 0)
18107 return;
18108 for (i = 0; i < nbItems; i++) {
18109 item = items[i];
18110 switch (item->type) {
18111 case XML_SCHEMA_TYPE_ELEMENT:
18112 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18113 NULL, NULL, NULL);
18114 break;
18115 default:
18116 break;
18117 }
18118 }
18119 if (ctxt->nberrors != 0)
18120 return;
18121
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018122 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018123 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018124 */
18125 for (i = 0; i < nbItems; i++) {
18126 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018127 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018128 case XML_SCHEMA_TYPE_SIMPLE:
18129 case XML_SCHEMA_TYPE_COMPLEX:
18130 xmlSchemaTypeFixup(item, ctxt, NULL);
18131 break;
18132 default:
18133 break;
18134 }
18135 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018136 if (ctxt->nberrors != 0)
18137 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018138 /*
18139 * Validate value contraint values.
18140 */
18141 for (i = 0; i < nbItems; i++) {
18142 item = items[i];
18143 switch (item->type) {
18144 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018145 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18146 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018147 break;
18148 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018149 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018150 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018151 break;
18152 default:
18153 break;
18154 }
18155 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018156 if (ctxt->nberrors != 0)
18157 return;
18158 /*
18159 * Build the content model for complex types.
18160 */
18161 for (i = 0; i < nbItems; i++) {
18162 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018163 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018164 case XML_SCHEMA_TYPE_COMPLEX:
18165 xmlSchemaBuildContentModel(item, ctxt, NULL);
18166 break;
18167 default:
18168 break;
18169 }
18170 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018171}
18172
18173/**
18174 * xmlSchemaAssembleByLocation:
18175 * @pctxt: a schema parser context
18176 * @vctxt: a schema validation context
18177 * @schema: the existing schema
18178 * @node: the node that fired the assembling
18179 * @nsName: the namespace name of the new schema
18180 * @location: the location of the schema
18181 *
18182 * Expands an existing schema by an additional schema.
18183 *
18184 * Returns 0 if the new schema is correct, a positive error code
18185 * number otherwise and -1 in case of an internal or API error.
18186 */
18187static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018188xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018189 xmlSchemaPtr schema,
18190 xmlNodePtr node,
18191 const xmlChar *nsName,
18192 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018193{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018194 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018195 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018196 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018197 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018198 xmlSchemaParserCtxtPtr pctxt;
18199
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018200 /*
18201 * This should be used:
18202 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018203 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018204 * 3. if requested via the API
18205 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018206 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018207 return (-1);
18208 /*
18209 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018210 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018211 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018212 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18213 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018214 pctxt = vctxt->pctxt;
18215 /*
18216 * Set the counter to produce unique names for anonymous items.
18217 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018218 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018219 /*
18220 * Acquire the schema document.
18221 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018222 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18223 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018224 if (ret != 0) {
18225 if (doc != NULL)
18226 xmlFreeDoc(doc);
18227 } else if (doc != NULL) {
18228 docElem = xmlDocGetRootElement(doc);
18229 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018230 * Create new assemble info.
18231 */
18232 if (pctxt->assemble == NULL) {
18233 pctxt->assemble = xmlSchemaNewAssemble();
18234 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018235 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018236 "Memory error: xmlSchemaAssembleByLocation, "
18237 "allocating assemble info", NULL);
18238 xmlFreeDoc(doc);
18239 return (-1);
18240 }
18241 }
18242 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018243 * Save and reset the context & schema.
18244 */
18245 oldflags = schema->flags;
18246 oldtns = schema->targetNamespace;
18247 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018248 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018249
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018250 xmlSchemaClearSchemaDefaults(schema);
18251 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018252 if ((targetNs != NULL) &&
18253 xmlStrEqual(targetNs, xmlSchemaNs)) {
18254 /*
18255 * We are parsing the schema for schema!
18256 */
18257 vctxt->pctxt->isS4S = 1;
18258 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018259 /* schema->nbCurItems = 0; */
18260 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018261 pctxt->ctxtType = NULL;
18262 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018263
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018264 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18265 if (pctxt->nberrors != 0) {
18266 vctxt->nberrors += pctxt->nberrors;
18267 goto finally;
18268 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018269 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018270 if (pctxt->nberrors != 0) {
18271 vctxt->nberrors += pctxt->nberrors;
18272 goto finally;
18273 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018274 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018275 if (pctxt->nberrors != 0)
18276 vctxt->nberrors += pctxt->nberrors;
18277finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018278 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018279 * Set the counter of items.
18280 */
18281 schema->counter = pctxt->counter;
18282 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018283 * Free the list of assembled components.
18284 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018285 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018286 /*
18287 * Restore the context & schema.
18288 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018289 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018290 schema->flags = oldflags;
18291 schema->targetNamespace = oldtns;
18292 schema->doc = olddoc;
18293 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018294 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018295 return (ret);
18296}
18297
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018298static xmlSchemaAttrInfoPtr
18299xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18300 int metaType)
18301{
18302 if (vctxt->nbAttrInfos == 0)
18303 return (NULL);
18304 {
18305 int i;
18306 xmlSchemaAttrInfoPtr iattr;
18307
18308 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18309 iattr = vctxt->attrInfos[i];
18310 if (iattr->metaType == metaType)
18311 return (iattr);
18312 }
18313
18314 }
18315 return (NULL);
18316}
18317
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018318/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018319 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018320 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018321 *
18322 * Expands an existing schema by an additional schema using
18323 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18324 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18325 * must be set to 1.
18326 *
18327 * Returns 0 if the new schema is correct, a positive error code
18328 * number otherwise and -1 in case of an internal or API error.
18329 */
18330static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018331xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018332{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018333 const xmlChar *cur, *end;
18334 const xmlChar *nsname = NULL, *location;
18335 int count = 0;
18336 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018337 xmlSchemaAttrInfoPtr iattr;
18338
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018339 /*
18340 * Parse the value; we will assume an even number of values
18341 * to be given (this is how Xerces and XSV work).
18342 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018343 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18344 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18345 if (iattr == NULL)
18346 xmlSchemaGetMetaAttrInfo(vctxt,
18347 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18348 if (iattr == NULL)
18349 return (0);
18350 cur = iattr->value;
18351 do {
18352 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018353 /*
18354 * Get the namespace name.
18355 */
18356 while (IS_BLANK_CH(*cur))
18357 cur++;
18358 end = cur;
18359 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18360 end++;
18361 if (end == cur)
18362 break;
18363 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018364 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018365 cur = end;
18366 }
18367 /*
18368 * Get the URI.
18369 */
18370 while (IS_BLANK_CH(*cur))
18371 cur++;
18372 end = cur;
18373 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18374 end++;
18375 if (end == cur)
18376 break;
18377 count++;
18378 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018379 cur = end;
18380 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18381 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018382 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018383 VERROR_INT("xmlSchemaAssembleByXSI",
18384 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018385 return (-1);
18386 }
18387 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018388 return (ret);
18389}
18390
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018391#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018392
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018393static const xmlChar *
18394xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18395 const xmlChar *prefix)
18396{
18397 if (vctxt->sax != NULL) {
18398 int i, j;
18399 xmlSchemaNodeInfoPtr inode;
18400
18401 for (i = vctxt->depth; i >= 0; i--) {
18402 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18403 inode = vctxt->elemInfos[i];
18404 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18405 if (((prefix == NULL) &&
18406 (inode->nsBindings[j] == NULL)) ||
18407 ((prefix != NULL) && xmlStrEqual(prefix,
18408 inode->nsBindings[j]))) {
18409
18410 /*
18411 * Note that the namespace bindings are already
18412 * in a string dict.
18413 */
18414 return (inode->nsBindings[j+1]);
18415 }
18416 }
18417 }
18418 }
18419 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018420#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018421 } else if (vctxt->reader != NULL) {
18422 xmlChar *nsName;
18423
18424 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18425 if (nsName != NULL) {
18426 const xmlChar *ret;
18427
18428 VAL_CREATE_DICT;
18429 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18430 xmlFree(nsName);
18431 return (ret);
18432 } else
18433 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018434#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018435 } else {
18436 xmlNsPtr ns;
18437
18438 if ((vctxt->inode->node == NULL) ||
18439 (vctxt->inode->node->doc == NULL)) {
18440 VERROR_INT("xmlSchemaLookupNamespace",
18441 "no node or node's doc avaliable");
18442 return (NULL);
18443 }
18444 ns = xmlSearchNs(vctxt->inode->node->doc,
18445 vctxt->inode->node, prefix);
18446 if (ns != NULL)
18447 return (ns->href);
18448 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018449 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018450}
18451
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018452/*
18453* This one works on the schema of the validation context.
18454*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018455static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018456xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18457 xmlSchemaPtr schema,
18458 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018459 const xmlChar *value,
18460 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018461 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018462{
18463 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018464
18465 if (vctxt && (vctxt->schema == NULL)) {
18466 VERROR_INT("xmlSchemaValidateNotation",
18467 "a schema is needed on the validation context");
18468 return (-1);
18469 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018470 ret = xmlValidateQName(value, 1);
18471 if (ret != 0)
18472 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018473 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018474 xmlChar *localName = NULL;
18475 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018476
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018477 localName = xmlSplitQName2(value, &prefix);
18478 if (prefix != NULL) {
18479 const xmlChar *nsName = NULL;
18480
18481 if (vctxt != NULL)
18482 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18483 else if (node != NULL) {
18484 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18485 if (ns != NULL)
18486 nsName = ns->href;
18487 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018488 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018489 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018490 return (1);
18491 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018492 if (nsName == NULL) {
18493 xmlFree(prefix);
18494 xmlFree(localName);
18495 return (1);
18496 }
18497 if (xmlHashLookup2(schema->notaDecl, localName,
18498 nsName) != NULL) {
18499 if (valNeeded && (val != NULL)) {
18500 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18501 BAD_CAST xmlStrdup(nsName));
18502 if (*val == NULL)
18503 ret = -1;
18504 }
18505 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018506 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018507 xmlFree(prefix);
18508 xmlFree(localName);
18509 } else {
18510 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18511 if (valNeeded && (val != NULL)) {
18512 (*val) = xmlSchemaNewNOTATIONValue(
18513 BAD_CAST xmlStrdup(value), NULL);
18514 if (*val == NULL)
18515 ret = -1;
18516 }
18517 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018518 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018519 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018520 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018521 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018522}
18523
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018524/************************************************************************
18525 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018526 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018527 * *
18528 ************************************************************************/
18529
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018530/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018531 * xmlSchemaAugmentIDC:
18532 * @idcDef: the IDC definition
18533 *
18534 * Creates an augmented IDC definition item.
18535 *
18536 * Returns the item, or NULL on internal errors.
18537 */
18538static void
18539xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18540 xmlSchemaValidCtxtPtr vctxt)
18541{
18542 xmlSchemaIDCAugPtr aidc;
18543
18544 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18545 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018546 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018547 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18548 NULL);
18549 return;
18550 }
18551 aidc->bubbleDepth = -1;
18552 aidc->def = idcDef;
18553 aidc->next = NULL;
18554 if (vctxt->aidcs == NULL)
18555 vctxt->aidcs = aidc;
18556 else {
18557 aidc->next = vctxt->aidcs;
18558 vctxt->aidcs = aidc;
18559 }
18560}
18561
18562/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018563 * xmlSchemaIDCNewBinding:
18564 * @idcDef: the IDC definition of this binding
18565 *
18566 * Creates a new IDC binding.
18567 *
18568 * Returns the new binding in case of succeeded, NULL on internal errors.
18569 */
18570static xmlSchemaPSVIIDCBindingPtr
18571xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18572{
18573 xmlSchemaPSVIIDCBindingPtr ret;
18574
18575 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18576 sizeof(xmlSchemaPSVIIDCBinding));
18577 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018578 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018579 "allocating a PSVI IDC binding item", NULL);
18580 return (NULL);
18581 }
18582 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18583 ret->definition = idcDef;
18584 return (ret);
18585}
18586
18587/**
18588 * xmlSchemaIDCStoreNodeTableItem:
18589 * @vctxt: the WXS validation context
18590 * @item: the IDC node table item
18591 *
18592 * The validation context is used to store an IDC node table items.
18593 * They are stored to avoid copying them if IDC node-tables are merged
18594 * with corresponding parent IDC node-tables (bubbling).
18595 *
18596 * Returns 0 if succeeded, -1 on internal errors.
18597 */
18598static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018599xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018600 xmlSchemaPSVIIDCNodePtr item)
18601{
18602 /*
18603 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018604 */
18605 if (vctxt->idcNodes == NULL) {
18606 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018607 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18608 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018609 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018610 "allocating the IDC node table item list", NULL);
18611 return (-1);
18612 }
18613 vctxt->sizeIdcNodes = 20;
18614 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18615 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018616 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18617 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018618 sizeof(xmlSchemaPSVIIDCNodePtr));
18619 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018620 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018621 "re-allocating the IDC node table item list", NULL);
18622 return (-1);
18623 }
18624 }
18625 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018626
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018627 return (0);
18628}
18629
18630/**
18631 * xmlSchemaIDCStoreKey:
18632 * @vctxt: the WXS validation context
18633 * @item: the IDC key
18634 *
18635 * The validation context is used to store an IDC key.
18636 *
18637 * Returns 0 if succeeded, -1 on internal errors.
18638 */
18639static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018640xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018641 xmlSchemaPSVIIDCKeyPtr key)
18642{
18643 /*
18644 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018645 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018646 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018647 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018648 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18649 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018650 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018651 "allocating the IDC key storage list", NULL);
18652 return (-1);
18653 }
18654 vctxt->sizeIdcKeys = 40;
18655 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18656 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018657 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18658 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018659 sizeof(xmlSchemaPSVIIDCKeyPtr));
18660 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018661 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018662 "re-allocating the IDC key storage list", NULL);
18663 return (-1);
18664 }
18665 }
18666 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018667
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018668 return (0);
18669}
18670
18671/**
18672 * xmlSchemaIDCAppendNodeTableItem:
18673 * @bind: the IDC binding
18674 * @ntItem: the node-table item
18675 *
18676 * Appends the IDC node-table item to the binding.
18677 *
18678 * Returns 0 on success and -1 on internal errors.
18679 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018680static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018681xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18682 xmlSchemaPSVIIDCNodePtr ntItem)
18683{
18684 if (bind->nodeTable == NULL) {
18685 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018686 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018687 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18688 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018689 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018690 "allocating an array of IDC node-table items", NULL);
18691 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018692 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018693 } else if (bind->sizeNodes <= bind->nbNodes) {
18694 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018695 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18696 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018697 sizeof(xmlSchemaPSVIIDCNodePtr));
18698 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018699 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018700 "re-allocating an array of IDC node-table items", NULL);
18701 return(-1);
18702 }
18703 }
18704 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018705 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018706}
18707
18708/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018709 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018710 * @vctxt: the WXS validation context
18711 * @matcher: the IDC matcher
18712 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018713 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018714 * of the given matcher. If none found, a new one is created
18715 * and added to the IDC table.
18716 *
18717 * Returns an IDC binding or NULL on internal errors.
18718 */
18719static xmlSchemaPSVIIDCBindingPtr
18720xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18721 xmlSchemaIDCMatcherPtr matcher)
18722{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018723 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018724
18725 info = vctxt->elemInfos[matcher->depth];
18726
18727 if (info->idcTable == NULL) {
18728 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18729 if (info->idcTable == NULL)
18730 return (NULL);
18731 return(info->idcTable);
18732 } else {
18733 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018734
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018735 bind = info->idcTable;
18736 do {
18737 if (bind->definition == matcher->aidc->def)
18738 return(bind);
18739 if (bind->next == NULL) {
18740 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18741 if (bind->next == NULL)
18742 return (NULL);
18743 return(bind->next);
18744 }
18745 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018746 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018747 }
18748 return (NULL);
18749}
18750
18751/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018752 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018753 * @key: the IDC key
18754 *
18755 * Frees an IDC key together with its compiled value.
18756 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018757static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018758xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18759{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018760 if (key->val != NULL)
18761 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018762 xmlFree(key);
18763}
18764
18765/**
18766 * xmlSchemaIDCFreeBinding:
18767 *
18768 * Frees an IDC binding. Note that the node table-items
18769 * are not freed.
18770 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018771static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018772xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18773{
18774 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018775 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18776 int i;
18777 /*
18778 * Node-table items for keyrefs are not stored globally
18779 * to the validation context, since they are not bubbled.
18780 * We need to free them here.
18781 */
18782 for (i = 0; i < bind->nbNodes; i++) {
18783 xmlFree(bind->nodeTable[i]->keys);
18784 xmlFree(bind->nodeTable[i]);
18785 }
18786 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018787 xmlFree(bind->nodeTable);
18788 }
18789 xmlFree(bind);
18790}
18791
18792/**
18793 * xmlSchemaIDCFreeIDCTable:
18794 * @bind: the first IDC binding in the list
18795 *
18796 * Frees an IDC table, i.e. all the IDC bindings in the list.
18797 */
18798static void
18799xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18800{
18801 xmlSchemaPSVIIDCBindingPtr prev;
18802
18803 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018804 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018805 bind = bind->next;
18806 xmlSchemaIDCFreeBinding(prev);
18807 }
18808}
18809
18810/**
18811 * xmlSchemaIDCFreeMatcherList:
18812 * @matcher: the first IDC matcher in the list
18813 *
18814 * Frees a list of IDC matchers.
18815 */
18816static void
18817xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18818{
18819 xmlSchemaIDCMatcherPtr next;
18820
18821 while (matcher != NULL) {
18822 next = matcher->next;
18823 if (matcher->keySeqs != NULL) {
18824 int i;
18825 for (i = 0; i < matcher->sizeKeySeqs; i++)
18826 if (matcher->keySeqs[i] != NULL)
18827 xmlFree(matcher->keySeqs[i]);
18828 xmlFree(matcher->keySeqs);
18829 }
18830 xmlFree(matcher);
18831 matcher = next;
18832 }
18833}
18834
18835/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018836 * xmlSchemaIDCAddStateObject:
18837 * @vctxt: the WXS validation context
18838 * @matcher: the IDC matcher
18839 * @sel: the XPath information
18840 * @parent: the parent "selector" state object if any
18841 * @type: "selector" or "field"
18842 *
18843 * Creates/reuses and activates state objects for the given
18844 * XPath information; if the XPath expression consists of unions,
18845 * multiple state objects are created for every unioned expression.
18846 *
18847 * Returns 0 on success and -1 on internal errors.
18848 */
18849static int
18850xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18851 xmlSchemaIDCMatcherPtr matcher,
18852 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018853 int type)
18854{
18855 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018856
18857 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018858 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018859 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018860 if (vctxt->xpathStatePool != NULL) {
18861 sto = vctxt->xpathStatePool;
18862 vctxt->xpathStatePool = sto->next;
18863 sto->next = NULL;
18864 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018865 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018866 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018867 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018868 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18869 if (sto == NULL) {
18870 xmlSchemaVErrMemory(NULL,
18871 "allocating an IDC state object", NULL);
18872 return (-1);
18873 }
18874 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18875 }
18876 /*
18877 * Add to global list.
18878 */
18879 if (vctxt->xpathStates != NULL)
18880 sto->next = vctxt->xpathStates;
18881 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018882
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018883 /*
18884 * Free the old xpath validation context.
18885 */
18886 if (sto->xpathCtxt != NULL)
18887 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18888
18889 /*
18890 * Create a new XPath (pattern) validation context.
18891 */
18892 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18893 (xmlPatternPtr) sel->xpathComp);
18894 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018895 VERROR_INT("xmlSchemaIDCAddStateObject",
18896 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018897 return (-1);
18898 }
18899 sto->type = type;
18900 sto->depth = vctxt->depth;
18901 sto->matcher = matcher;
18902 sto->sel = sel;
18903 sto->nbHistory = 0;
18904
18905#if DEBUG_IDC
18906 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18907 sto->sel->xpath);
18908#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018909 return (0);
18910}
18911
18912/**
18913 * xmlSchemaXPathEvaluate:
18914 * @vctxt: the WXS validation context
18915 * @nodeType: the nodeType of the current node
18916 *
18917 * Evaluates all active XPath state objects.
18918 *
18919 * Returns the number of IC "field" state objects which resolved to
18920 * this node, 0 if none resolved and -1 on internal errors.
18921 */
18922static int
18923xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018924 xmlElementType nodeType)
18925{
18926 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018927 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018928
18929 if (vctxt->xpathStates == NULL)
18930 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018931
18932 if (nodeType == XML_ATTRIBUTE_NODE)
18933 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018934#if DEBUG_IDC
18935 {
18936 xmlChar *str = NULL;
18937 xmlGenericError(xmlGenericErrorContext,
18938 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018939 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18940 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018941 FREE_AND_NULL(str)
18942 }
18943#endif
18944 /*
18945 * Process all active XPath state objects.
18946 */
18947 first = vctxt->xpathStates;
18948 sto = first;
18949 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018950#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018951 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018952 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18953 sto->matcher->aidc->def->name, sto->sel->xpath);
18954 else
18955 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18956 sto->matcher->aidc->def->name, sto->sel->xpath);
18957#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018958 if (nodeType == XML_ELEMENT_NODE)
18959 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018960 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018961 else
18962 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018963 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018964
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018965 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018966 VERROR_INT("xmlSchemaXPathEvaluate",
18967 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018968 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018969 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018970 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018971 goto next_sto;
18972 /*
18973 * Full match.
18974 */
18975#if DEBUG_IDC
18976 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018977 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018978#endif
18979 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018980 * Register a match in the state object history.
18981 */
18982 if (sto->history == NULL) {
18983 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18984 if (sto->history == NULL) {
18985 xmlSchemaVErrMemory(NULL,
18986 "allocating the state object history", NULL);
18987 return(-1);
18988 }
18989 sto->sizeHistory = 10;
18990 } else if (sto->sizeHistory <= sto->nbHistory) {
18991 sto->sizeHistory *= 2;
18992 sto->history = (int *) xmlRealloc(sto->history,
18993 sto->sizeHistory * sizeof(int));
18994 if (sto->history == NULL) {
18995 xmlSchemaVErrMemory(NULL,
18996 "re-allocating the state object history", NULL);
18997 return(-1);
18998 }
18999 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019000 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019001
19002#ifdef DEBUG_IDC
19003 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19004 vctxt->depth);
19005#endif
19006
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019007 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19008 xmlSchemaIDCSelectPtr sel;
19009 /*
19010 * Activate state objects for the IDC fields of
19011 * the IDC selector.
19012 */
19013#if DEBUG_IDC
19014 xmlGenericError(xmlGenericErrorContext, "IDC: "
19015 "activating field states\n");
19016#endif
19017 sel = sto->matcher->aidc->def->fields;
19018 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019019 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19020 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19021 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019022 sel = sel->next;
19023 }
19024 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19025 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019026 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019027 */
19028#if DEBUG_IDC
19029 xmlGenericError(xmlGenericErrorContext,
19030 "IDC: key found\n");
19031#endif
19032 /*
19033 * Notify that the character value of this node is
19034 * needed.
19035 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019036 if (resolved == 0) {
19037 if ((vctxt->inode->flags &
19038 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19039 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19040 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019041 resolved++;
19042 }
19043next_sto:
19044 if (sto->next == NULL) {
19045 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019046 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019047 */
19048 head = first;
19049 sto = vctxt->xpathStates;
19050 } else
19051 sto = sto->next;
19052 }
19053 return (resolved);
19054}
19055
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019056static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019057xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019058 xmlChar **buf,
19059 xmlSchemaPSVIIDCKeyPtr *seq,
19060 int count)
19061{
19062 int i, res;
19063 const xmlChar *value = NULL;
19064
19065 *buf = xmlStrdup(BAD_CAST "[");
19066 for (i = 0; i < count; i++) {
19067 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019068 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19069 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019070 if (res == 0)
19071 *buf = xmlStrcat(*buf, value);
19072 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019073 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19074 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019075 *buf = xmlStrcat(*buf, BAD_CAST "???");
19076 }
19077 if (i < count -1)
19078 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19079 else
19080 *buf = xmlStrcat(*buf, BAD_CAST "'");
19081 if (value != NULL) {
19082 xmlFree((xmlChar *) value);
19083 value = NULL;
19084 }
19085 }
19086 *buf = xmlStrcat(*buf, BAD_CAST "]");
19087
19088 return (BAD_CAST *buf);
19089}
19090
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019091/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019092 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019093 * @vctxt: the WXS validation context
19094 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019095 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019096 *
19097 * Processes and pops the history items of the IDC state objects.
19098 * IDC key-sequences are validated/created on IDC bindings.
19099 *
19100 * Returns 0 on success and -1 on internal errors.
19101 */
19102static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019103xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019104 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019105{
19106 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019107 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019108 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019109 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019110
19111 if (vctxt->xpathStates == NULL)
19112 return (0);
19113 sto = vctxt->xpathStates;
19114
19115#if DEBUG_IDC
19116 {
19117 xmlChar *str = NULL;
19118 xmlGenericError(xmlGenericErrorContext,
19119 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019120 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19121 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019122 FREE_AND_NULL(str)
19123 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019124#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019125 /*
19126 * Evaluate the state objects.
19127 */
19128 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019129 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19130 if (res == -1) {
19131 VERROR_INT("xmlSchemaXPathProcessHistory",
19132 "calling xmlStreamPop()");
19133 return (-1);
19134 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019135#if DEBUG_IDC
19136 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19137 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019138#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019139 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019140 goto deregister_check;
19141
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019142 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019143
19144 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019145 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019146 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019147 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019148 sto = sto->next;
19149 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019150 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019151 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19152 if (! IS_SIMPLE_TYPE(type)) {
19153 /*
19154 * Not qualified if the field resolves to a node of non
19155 * simple type.
19156 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019157 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19158 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019159 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19160 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019161 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019162
19163 sto->nbHistory--;
19164 goto deregister_check;
19165 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019166 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019167 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019168 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019169 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019170 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019171 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019172 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19173 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019174 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019175 sto->nbHistory--;
19176 goto deregister_check;
19177 } else {
19178 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19179 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019180 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019181
19182 /*
19183 * The key will be anchored on the matcher's list of
19184 * key-sequences. The position in this list is determined
19185 * by the target node's depth relative to the matcher's
19186 * depth of creation (i.e. the depth of the scope element).
19187 */
19188 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019189 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019190
19191 /*
19192 * Create/grow the array of key-sequences.
19193 */
19194 if (matcher->keySeqs == NULL) {
19195 if (pos > 9)
19196 matcher->sizeKeySeqs = pos * 2;
19197 else
19198 matcher->sizeKeySeqs = 10;
19199 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19200 xmlMalloc(matcher->sizeKeySeqs *
19201 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19202 if (matcher->keySeqs == NULL) {
19203 xmlSchemaVErrMemory(NULL,
19204 "allocating an array of key-sequences",
19205 NULL);
19206 return(-1);
19207 }
19208 memset(matcher->keySeqs, 0,
19209 matcher->sizeKeySeqs *
19210 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19211 } else if (pos >= matcher->sizeKeySeqs) {
19212 int i = matcher->sizeKeySeqs;
19213
19214 matcher->sizeKeySeqs *= 2;
19215 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19216 xmlRealloc(matcher->keySeqs,
19217 matcher->sizeKeySeqs *
19218 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019219 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019220 xmlSchemaVErrMemory(NULL,
19221 "reallocating an array of key-sequences",
19222 NULL);
19223 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019224 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019225 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019226 * The array needs to be NULLed.
19227 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019228 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019229 for (; i < matcher->sizeKeySeqs; i++)
19230 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019231 }
19232
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019233 /*
19234 * Get/create the key-sequence.
19235 */
19236 keySeq = matcher->keySeqs[pos];
19237 if (keySeq == NULL) {
19238 goto create_sequence;
19239 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019240 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019241 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019242 * cvc-identity-constraint:
19243 * 3 For each node in the ·target node set· all
19244 * of the {fields}, with that node as the context
19245 * node, evaluate to either an empty node-set or
19246 * a node-set with exactly one member, which must
19247 * have a simple type.
19248 *
19249 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019250 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019251 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19252 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019253 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019254 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019255 "with more than one member",
19256 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019257 sto->nbHistory--;
19258 goto deregister_check;
19259 } else {
19260 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019261 }
19262 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019263
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019264create_sequence:
19265 /*
19266 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019267 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019268 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19269 matcher->aidc->def->nbFields *
19270 sizeof(xmlSchemaPSVIIDCKeyPtr));
19271 if (keySeq == NULL) {
19272 xmlSchemaVErrMemory(NULL,
19273 "allocating an IDC key-sequence", NULL);
19274 return(-1);
19275 }
19276 memset(keySeq, 0, matcher->aidc->def->nbFields *
19277 sizeof(xmlSchemaPSVIIDCKeyPtr));
19278 matcher->keySeqs[pos] = keySeq;
19279create_key:
19280 /*
19281 * Created a key once per node only.
19282 */
19283 if (key == NULL) {
19284 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19285 sizeof(xmlSchemaPSVIIDCKey));
19286 if (key == NULL) {
19287 xmlSchemaVErrMemory(NULL,
19288 "allocating a IDC key", NULL);
19289 xmlFree(keySeq);
19290 matcher->keySeqs[pos] = NULL;
19291 return(-1);
19292 }
19293 /*
19294 * Consume the compiled value.
19295 */
19296 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019297 key->val = vctxt->inode->val;
19298 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019299 /*
19300 * Store the key in a global list.
19301 */
19302 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19303 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019304 return (-1);
19305 }
19306 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019307 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019308 }
19309 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019310
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019311 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19312 xmlSchemaPSVIIDCBindingPtr bind;
19313 xmlSchemaPSVIIDCNodePtr ntItem;
19314 xmlSchemaIDCMatcherPtr matcher;
19315 xmlSchemaIDCPtr idc;
19316 int pos, i, j, nbKeys;
19317 /*
19318 * Here we have the following scenario:
19319 * An IDC 'selector' state object resolved to a target node,
19320 * during the time this target node was in the
19321 * ancestor-or-self axis, the 'field' state object(s) looked
19322 * out for matching nodes to create a key-sequence for this
19323 * target node. Now we are back to this target node and need
19324 * to put the key-sequence, together with the target node
19325 * itself, into the node-table of the corresponding IDC
19326 * binding.
19327 */
19328 matcher = sto->matcher;
19329 idc = matcher->aidc->def;
19330 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019331 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019332 /*
19333 * Check if the matcher has any key-sequences at all, plus
19334 * if it has a key-sequence for the current target node.
19335 */
19336 if ((matcher->keySeqs == NULL) ||
19337 (matcher->sizeKeySeqs <= pos)) {
19338 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19339 goto selector_key_error;
19340 else
19341 goto selector_leave;
19342 }
19343
19344 keySeq = &(matcher->keySeqs[pos]);
19345 if (*keySeq == NULL) {
19346 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19347 goto selector_key_error;
19348 else
19349 goto selector_leave;
19350 }
19351
19352 for (i = 0; i < nbKeys; i++) {
19353 if ((*keySeq)[i] == NULL) {
19354 /*
19355 * Not qualified, if not all fields did resolve.
19356 */
19357 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19358 /*
19359 * All fields of a "key" IDC must resolve.
19360 */
19361 goto selector_key_error;
19362 }
19363 goto selector_leave;
19364 }
19365 }
19366 /*
19367 * All fields did resolve.
19368 */
19369
19370 /*
19371 * 4.1 If the {identity-constraint category} is unique(/key),
19372 * then no two members of the ·qualified node set· have
19373 * ·key-sequences· whose members are pairwise equal, as
19374 * defined by Equal in [XML Schemas: Datatypes].
19375 *
19376 * Get the IDC binding from the matcher and check for
19377 * duplicate key-sequences.
19378 */
19379 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19380 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19381 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019382 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019383
19384 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019385 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019386 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019387 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019388 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019389 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019390 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019391 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019392 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019393 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019394 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019395 if (res == -1) {
19396 return (-1);
19397 } else if (res == 0)
19398 break;
19399 }
19400 if (res == 1) {
19401 /*
19402 * Duplicate found.
19403 */
19404 break;
19405 }
19406 i++;
19407 } while (i < bind->nbNodes);
19408 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019409 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019410 /*
19411 * TODO: Try to report the key-sequence.
19412 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019413 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19414 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019415 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019416 "Duplicate key-sequence %s",
19417 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19418 (*keySeq), nbKeys), NULL);
19419 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019420 goto selector_leave;
19421 }
19422 }
19423 /*
19424 * Add a node-table item to the IDC binding.
19425 */
19426 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19427 sizeof(xmlSchemaPSVIIDCNode));
19428 if (ntItem == NULL) {
19429 xmlSchemaVErrMemory(NULL,
19430 "allocating an IDC node-table item", NULL);
19431 xmlFree(*keySeq);
19432 *keySeq = NULL;
19433 return(-1);
19434 }
19435 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19436
19437 /*
19438 * Store the node-table item on global list.
19439 */
19440 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19441 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19442 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019443 xmlFree(*keySeq);
19444 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019445 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019446 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019447 }
19448 /*
19449 * Init the node-table item. Consume the key-sequence.
19450 */
19451 ntItem->node = vctxt->node;
19452 ntItem->keys = *keySeq;
19453 *keySeq = NULL;
19454 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19455 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19456 /*
19457 * Free the item, since keyref items won't be
19458 * put on a global list.
19459 */
19460 xmlFree(ntItem->keys);
19461 xmlFree(ntItem);
19462 }
19463 return (-1);
19464 }
19465
19466 goto selector_leave;
19467selector_key_error:
19468 /*
19469 * 4.2.1 (KEY) The ·target node set· and the
19470 * ·qualified node set· are equal, that is, every
19471 * member of the ·target node set· is also a member
19472 * of the ·qualified node set· and vice versa.
19473 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019474 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19475 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019476selector_leave:
19477 /*
19478 * Free the key-sequence if not added to the IDC table.
19479 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019480 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019481 xmlFree(*keySeq);
19482 *keySeq = NULL;
19483 }
19484 } /* if selector */
19485
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019486 sto->nbHistory--;
19487
19488deregister_check:
19489 /*
19490 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019491 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019492 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019493#if DEBUG_IDC
19494 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19495 sto->sel->xpath);
19496#endif
19497 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019498 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019499 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019500 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019501 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019502 nextsto = sto->next;
19503 /*
19504 * Unlink from the list of active XPath state objects.
19505 */
19506 vctxt->xpathStates = sto->next;
19507 sto->next = vctxt->xpathStatePool;
19508 /*
19509 * Link it to the pool of reusable state objects.
19510 */
19511 vctxt->xpathStatePool = sto;
19512 sto = nextsto;
19513 } else
19514 sto = sto->next;
19515 } /* while (sto != NULL) */
19516 return (0);
19517}
19518
19519/**
19520 * xmlSchemaIDCRegisterMatchers:
19521 * @vctxt: the WXS validation context
19522 * @elemDecl: the element declaration
19523 *
19524 * Creates helper objects to evaluate IDC selectors/fields
19525 * successively.
19526 *
19527 * Returns 0 if OK and -1 on internal errors.
19528 */
19529static int
19530xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19531 xmlSchemaElementPtr elemDecl)
19532{
19533 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19534 xmlSchemaIDCPtr idc, refIdc;
19535 xmlSchemaIDCAugPtr aidc;
19536
19537 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19538 if (idc == NULL)
19539 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019540
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019541#if DEBUG_IDC
19542 {
19543 xmlChar *str = NULL;
19544 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019545 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019546 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19547 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019548 FREE_AND_NULL(str)
19549 }
19550#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019551 if (vctxt->inode->idcMatchers != NULL) {
19552 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19553 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019554 return (-1);
19555 }
19556 do {
19557 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19558 /*
19559 * Since IDCs bubbles are expensive we need to know the
19560 * depth at which the bubbles should stop; this will be
19561 * the depth of the top-most keyref IDC. If no keyref
19562 * references a key/unique IDC, the bubbleDepth will
19563 * be -1, indicating that no bubbles are needed.
19564 */
19565 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19566 if (refIdc != NULL) {
19567 /*
19568 * Lookup the augmented IDC.
19569 */
19570 aidc = vctxt->aidcs;
19571 while (aidc != NULL) {
19572 if (aidc->def == refIdc)
19573 break;
19574 aidc = aidc->next;
19575 }
19576 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019577 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019578 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019579 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019580 return (-1);
19581 }
19582 if ((aidc->bubbleDepth == -1) ||
19583 (vctxt->depth < aidc->bubbleDepth))
19584 aidc->bubbleDepth = vctxt->depth;
19585 }
19586 }
19587 /*
19588 * Lookup the augmented IDC item for the IDC definition.
19589 */
19590 aidc = vctxt->aidcs;
19591 while (aidc != NULL) {
19592 if (aidc->def == idc)
19593 break;
19594 aidc = aidc->next;
19595 }
19596 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019597 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19598 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019599 return (-1);
19600 }
19601 /*
19602 * Create an IDC matcher for every IDC definition.
19603 */
19604 matcher = (xmlSchemaIDCMatcherPtr)
19605 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19606 if (matcher == NULL) {
19607 xmlSchemaVErrMemory(vctxt,
19608 "allocating an IDC matcher", NULL);
19609 return (-1);
19610 }
19611 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19612 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019613 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019614 else
19615 last->next = matcher;
19616 last = matcher;
19617
19618 matcher->type = IDC_MATCHER;
19619 matcher->depth = vctxt->depth;
19620 matcher->aidc = aidc;
19621#if DEBUG_IDC
19622 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19623#endif
19624 /*
19625 * Init the automaton state object.
19626 */
19627 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019628 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019629 return (-1);
19630
19631 idc = idc->next;
19632 } while (idc != NULL);
19633 return (0);
19634}
19635
19636/**
19637 * xmlSchemaBubbleIDCNodeTables:
19638 * @depth: the current tree depth
19639 *
19640 * Merges IDC bindings of an element at @depth into the corresponding IDC
19641 * bindings of its parent element. If a duplicate note-table entry is found,
19642 * both, the parent node-table entry and child entry are discarded from the
19643 * node-table of the parent.
19644 *
19645 * Returns 0 if OK and -1 on internal errors.
19646 */
19647static int
19648xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19649{
19650 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019651 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19652 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019653 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19654 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019655 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019656 int duplTop;
19657
19658 /*
19659 * The node table has the following sections:
19660 *
19661 * O --> old node-table entries (first)
19662 * O
19663 * + --> new node-table entries
19664 * +
19665 * % --> new duplicate node-table entries
19666 * %
19667 * # --> old duplicate node-table entries
19668 * # (last)
19669 *
19670 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019671 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019672 if (bind == NULL) {
19673 /* Fine, no table, no bubbles. */
19674 return (0);
19675 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019676
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019677 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19678 /*
19679 * Walk all bindings; create new or add to existing bindings.
19680 * Remove duplicate key-sequences.
19681 */
19682start_binding:
19683 while (bind != NULL) {
19684 /*
19685 * Skip keyref IDCs.
19686 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019687 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19688 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019689 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019690 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019691 /*
19692 * Check if the key/unique IDC table needs to be bubbled.
19693 */
19694 aidc = vctxt->aidcs;
19695 do {
19696 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019697 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019698 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019699 bind = bind->next;
19700 goto start_binding;
19701 }
19702 break;
19703 }
19704 aidc = aidc->next;
19705 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019706
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019707 if (parTable != NULL)
19708 parBind = *parTable;
19709 while (parBind != NULL) {
19710 /*
19711 * Search a matching parent binding for the
19712 * IDC definition.
19713 */
19714 if (parBind->definition == bind->definition) {
19715
19716 /*
19717 * Compare every node-table entry of the child node,
19718 * i.e. the key-sequence within, ...
19719 */
19720 oldNum = parBind->nbNodes; /* Skip newly added items. */
19721 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019722 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019723
19724 for (i = 0; i < bind->nbNodes; i++) {
19725 node = bind->nodeTable[i];
19726 if (node == NULL)
19727 continue;
19728 /*
19729 * ...with every key-sequence of the parent node, already
19730 * evaluated to be a duplicate key-sequence.
19731 */
19732 if (parBind->nbDupls != 0) {
19733 j = bind->nbNodes + newDupls;
19734 while (j < duplTop) {
19735 parNode = parBind->nodeTable[j];
19736 for (k = 0; k < bind->definition->nbFields; k++) {
19737 key = node->keys[k];
19738 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019739 ret = xmlSchemaAreValuesEqual(key->val,
19740 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019741 if (ret == -1) {
19742 /* TODO: Internal error */
19743 return(-1);
19744 } else if (ret == 0)
19745 break;
19746
19747 }
19748 if (ret == 1)
19749 /* Duplicate found. */
19750 break;
19751 j++;
19752 }
19753 if (j != duplTop) {
19754 /* Duplicate found. */
19755 continue;
19756 }
19757 }
19758 /*
19759 * ... and with every key-sequence of the parent node.
19760 */
19761 j = 0;
19762 while (j < oldNum) {
19763 parNode = parBind->nodeTable[j];
19764 /*
19765 * Compare key by key.
19766 */
19767 for (k = 0; k < parBind->definition->nbFields; k++) {
19768 key = node->keys[k];
19769 parKey = parNode->keys[k];
19770
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019771 ret = xmlSchemaAreValuesEqual(key->val,
19772 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019773 if (ret == -1) {
19774 /* TODO: Internal error */
19775 } else if (ret == 0)
19776 break;
19777
19778 }
19779 if (ret == 1)
19780 /*
19781 * The key-sequences are equal.
19782 */
19783 break;
19784 j++;
19785 }
19786 if (j != oldNum) {
19787 /*
19788 * Handle duplicates.
19789 */
19790 newDupls++;
19791 oldNum--;
19792 parBind->nbNodes--;
19793 /*
19794 * Move last old item to pos of duplicate.
19795 */
19796 parBind->nodeTable[j] =
19797 parBind->nodeTable[oldNum];
19798
19799 if (parBind->nbNodes != oldNum) {
19800 /*
19801 * If new items exist, move last new item to
19802 * last of old items.
19803 */
19804 parBind->nodeTable[oldNum] =
19805 parBind->nodeTable[parBind->nbNodes];
19806 }
19807 /*
19808 * Move duplicate to last pos of new/old items.
19809 */
19810 parBind->nodeTable[parBind->nbNodes] = parNode;
19811
19812 } else {
19813 /*
19814 * Add the node-table entry (node and key-sequence) of
19815 * the child node to the node table of the parent node.
19816 */
19817 if (parBind->nodeTable == NULL) {
19818 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019819 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019820 if (parBind->nodeTable == NULL) {
19821 xmlSchemaVErrMemory(NULL,
19822 "allocating IDC list of node-table items", NULL);
19823 return(-1);
19824 }
19825 parBind->sizeNodes = 1;
19826 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019827 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019828 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19829 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19830 sizeof(xmlSchemaPSVIIDCNodePtr));
19831 if (parBind->nodeTable == NULL) {
19832 xmlSchemaVErrMemory(NULL,
19833 "re-allocating IDC list of node-table items", NULL);
19834 return(-1);
19835 }
19836 }
19837
19838 /*
19839 * Move first old duplicate to last position
19840 * of old duplicates +1.
19841 */
19842 if (parBind->nbDupls != 0) {
19843 parBind->nodeTable[duplTop] =
19844 parBind->nodeTable[parBind->nbNodes + newDupls];
19845 }
19846 /*
19847 * Move first new duplicate to last position of
19848 * new duplicates +1.
19849 */
19850 if (newDupls != 0) {
19851 parBind->nodeTable[parBind->nbNodes + newDupls] =
19852 parBind->nodeTable[parBind->nbNodes];
19853 }
19854 /*
19855 * Append the new node-table entry to the 'new node-table
19856 * entries' section.
19857 */
19858 parBind->nodeTable[parBind->nbNodes] = node;
19859 parBind->nbNodes++;
19860 duplTop++;
19861 }
19862 }
19863 parBind->nbDupls += newDupls;
19864 break;
19865 }
19866 if (parBind->next == NULL)
19867 lastParBind = parBind;
19868 parBind = parBind->next;
19869 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019870 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019871 /*
19872 * No binding for the IDC was found: create a new one and
19873 * copy all node-tables.
19874 */
19875 parBind = xmlSchemaIDCNewBinding(bind->definition);
19876 if (parBind == NULL)
19877 return(-1);
19878
19879 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19880 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19881 if (parBind->nodeTable == NULL) {
19882 xmlSchemaVErrMemory(NULL,
19883 "allocating an array of IDC node-table items", NULL);
19884 xmlSchemaIDCFreeBinding(parBind);
19885 return(-1);
19886 }
19887 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019888 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019889 memcpy(parBind->nodeTable, bind->nodeTable,
19890 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019891 if (*parTable == NULL)
19892 *parTable = parBind;
19893 else
19894 lastParBind->next = parBind;
19895 }
19896 bind = bind->next;
19897 }
19898 return (0);
19899}
19900
19901/**
19902 * xmlSchemaCheckCVCIDCKeyRef:
19903 * @vctxt: the WXS validation context
19904 * @elemDecl: the element declaration
19905 *
19906 * Check the cvc-idc-keyref constraints.
19907 */
19908static int
19909xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19910{
19911 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19912
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019913 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019914 /*
19915 * Find a keyref.
19916 */
19917 while (refbind != NULL) {
19918 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19919 int i, j, k, res;
19920 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19921 xmlSchemaPSVIIDCKeyPtr refKey, key;
19922
19923 /*
19924 * Find the referred key/unique.
19925 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019926 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019927 do {
19928 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19929 bind->definition)
19930 break;
19931 bind = bind->next;
19932 } while (bind != NULL);
19933
19934 /*
19935 * Search for a matching key-sequences.
19936 */
19937 for (i = 0; i < refbind->nbNodes; i++) {
19938 res = 0;
19939 if (bind != NULL) {
19940 refKeys = refbind->nodeTable[i]->keys;
19941 for (j = 0; j < bind->nbNodes; j++) {
19942 keys = bind->nodeTable[j]->keys;
19943 for (k = 0; k < bind->definition->nbFields; k++) {
19944 refKey = refKeys[k];
19945 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019946 res = xmlSchemaAreValuesEqual(key->val,
19947 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019948 if (res == 0)
19949 break;
19950 else if (res == -1) {
19951 return (-1);
19952 }
19953 }
19954 if (res == 1) {
19955 /*
19956 * Match found.
19957 */
19958 break;
19959 }
19960 }
19961 }
19962 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019963 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019964 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019965 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19966 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019967 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019968 "No match found for key-sequence %s of key "
19969 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019970 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019971 refbind->nodeTable[i]->keys,
19972 refbind->definition->nbFields),
19973 xmlSchemaFormatQName(&strB,
19974 refbind->definition->targetNamespace,
19975 refbind->definition->name));
19976 FREE_AND_NULL(str);
19977 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019978 }
19979 }
19980 }
19981 refbind = refbind->next;
19982 }
19983 return (0);
19984}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019985
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019986/************************************************************************
19987 * *
19988 * XML Reader validation code *
19989 * *
19990 ************************************************************************/
19991
19992static xmlSchemaAttrInfoPtr
19993xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019994{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019995 xmlSchemaAttrInfoPtr iattr;
19996 /*
19997 * Grow/create list of attribute infos.
19998 */
19999 if (vctxt->attrInfos == NULL) {
20000 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20001 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
20002 vctxt->sizeAttrInfos = 1;
20003 if (vctxt->attrInfos == NULL) {
20004 xmlSchemaVErrMemory(vctxt,
20005 "allocating attribute info list", NULL);
20006 return (NULL);
20007 }
20008 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
20009 vctxt->sizeAttrInfos++;
20010 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20011 xmlRealloc(vctxt->attrInfos,
20012 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
20013 if (vctxt->attrInfos == NULL) {
20014 xmlSchemaVErrMemory(vctxt,
20015 "re-allocating attribute info list", NULL);
20016 return (NULL);
20017 }
20018 } else {
20019 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
20020 if (iattr->localName != NULL) {
20021 VERROR_INT("xmlSchemaGetFreshAttrInfo",
20022 "attr info not cleared");
20023 return (NULL);
20024 }
20025 iattr->nodeType = XML_ATTRIBUTE_NODE;
20026 return (iattr);
20027 }
20028 /*
20029 * Create an attribute info.
20030 */
20031 iattr = (xmlSchemaAttrInfoPtr)
20032 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20033 if (iattr == NULL) {
20034 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20035 return (NULL);
20036 }
20037 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20038 iattr->nodeType = XML_ATTRIBUTE_NODE;
20039 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20040
20041 return (iattr);
20042}
20043
20044static int
20045xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20046 xmlNodePtr attrNode,
20047 const xmlChar *localName,
20048 const xmlChar *nsName,
20049 int ownedNames,
20050 xmlChar *value,
20051 int ownedValue)
20052{
20053 xmlSchemaAttrInfoPtr attr;
20054
20055 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20056 if (attr == NULL) {
20057 VERROR_INT("xmlSchemaPushAttribute",
20058 "calling xmlSchemaGetFreshAttrInfo()");
20059 return (-1);
20060 }
20061 attr->node = attrNode;
20062 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20063 attr->localName = localName;
20064 attr->nsName = nsName;
20065 if (ownedNames)
20066 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20067 /*
20068 * Evaluate if it's an XSI attribute.
20069 */
20070 if (nsName != NULL) {
20071 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20072 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20073 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20074 }
20075 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20076 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20077 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20078 }
20079 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20080 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20081 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20082 }
20083 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20084 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20085 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20086 }
20087 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20088 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20089 }
20090 }
20091 attr->value = value;
20092 if (ownedValue)
20093 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20094 if (attr->metaType != 0)
20095 attr->state = XML_SCHEMAS_ATTR_META;
20096 return (0);
20097}
20098
20099static void
20100xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20101{
20102 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20103 FREE_AND_NULL(ielem->localName);
20104 FREE_AND_NULL(ielem->nsName);
20105 } else {
20106 ielem->localName = NULL;
20107 ielem->nsName = NULL;
20108 }
20109 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20110 FREE_AND_NULL(ielem->value);
20111 } else {
20112 ielem->value = NULL;
20113 }
20114 if (ielem->val != NULL) {
20115 xmlSchemaFreeValue(ielem->val);
20116 ielem->val = NULL;
20117 }
20118 if (ielem->idcMatchers != NULL) {
20119 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20120 ielem->idcMatchers = NULL;
20121 }
20122 if (ielem->idcTable != NULL) {
20123 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20124 ielem->idcTable = NULL;
20125 }
20126 if (ielem->regexCtxt != NULL) {
20127 xmlRegFreeExecCtxt(ielem->regexCtxt);
20128 ielem->regexCtxt = NULL;
20129 }
20130 if (ielem->nsBindings != NULL) {
20131 xmlFree((xmlChar **)ielem->nsBindings);
20132 ielem->nsBindings = NULL;
20133 ielem->nbNsBindings = 0;
20134 ielem->sizeNsBindings = 0;
20135 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020136}
20137
20138/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020139 * xmlSchemaGetFreshElemInfo:
20140 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020141 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020142 * Creates/reuses and initializes the element info item for
20143 * the currect tree depth.
20144 *
20145 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020146 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020147static xmlSchemaNodeInfoPtr
20148xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020149{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020150 xmlSchemaNodeInfoPtr info = NULL;
20151
20152 if (vctxt->depth > vctxt->sizeElemInfos) {
20153 VERROR_INT("xmlSchemaGetFreshElemInfo",
20154 "inconsistent depth encountered");
20155 return (NULL);
20156 }
20157 if (vctxt->elemInfos == NULL) {
20158 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20159 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20160 if (vctxt->elemInfos == NULL) {
20161 xmlSchemaVErrMemory(vctxt,
20162 "allocating the element info array", NULL);
20163 return (NULL);
20164 }
20165 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20166 vctxt->sizeElemInfos = 10;
20167 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20168 int i = vctxt->sizeElemInfos;
20169
20170 vctxt->sizeElemInfos *= 2;
20171 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20172 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20173 sizeof(xmlSchemaNodeInfoPtr));
20174 if (vctxt->elemInfos == NULL) {
20175 xmlSchemaVErrMemory(vctxt,
20176 "re-allocating the element info array", NULL);
20177 return (NULL);
20178 }
20179 /*
20180 * We need the new memory to be NULLed.
20181 * TODO: Use memset instead?
20182 */
20183 for (; i < vctxt->sizeElemInfos; i++)
20184 vctxt->elemInfos[i] = NULL;
20185 } else
20186 info = vctxt->elemInfos[vctxt->depth];
20187
20188 if (info == NULL) {
20189 info = (xmlSchemaNodeInfoPtr)
20190 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20191 if (info == NULL) {
20192 xmlSchemaVErrMemory(vctxt,
20193 "allocating an element info", NULL);
20194 return (NULL);
20195 }
20196 vctxt->elemInfos[vctxt->depth] = info;
20197 } else {
20198 if (info->localName != NULL) {
20199 VERROR_INT("xmlSchemaGetFreshElemInfo",
20200 "elem info has not been cleared");
20201 return (NULL);
20202 }
20203 }
20204 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20205 info->nodeType = XML_ELEMENT_NODE;
20206 info->depth = vctxt->depth;
20207
20208 return (info);
20209}
20210
20211#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20212#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20213#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20214
20215static int
20216xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20217 xmlNodePtr node,
20218 xmlSchemaTypePtr type,
20219 xmlSchemaValType valType,
20220 const xmlChar * value,
20221 xmlSchemaValPtr val,
20222 unsigned long length,
20223 int fireErrors)
20224{
20225 int ret, error = 0;
20226
20227 xmlSchemaTypePtr tmpType;
20228 xmlSchemaFacetLinkPtr facetLink;
20229 xmlSchemaFacetPtr facet;
20230 unsigned long len = 0;
20231 xmlSchemaWhitespaceValueType ws;
20232
20233 /*
20234 * In Libxml2, derived built-in types have currently no explicit facets.
20235 */
20236 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020237 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020238
20239 /*
20240 * NOTE: Do not jump away, if the facetSet of the given type is
20241 * empty: until now, "pattern" and "enumeration" facets of the
20242 * *base types* need to be checked as well.
20243 */
20244 if (type->facetSet == NULL)
20245 goto pattern_and_enum;
20246
20247 if (! VARIETY_ATOMIC(type)) {
20248 if (VARIETY_LIST(type))
20249 goto variety_list;
20250 else
20251 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020252 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020253 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020254 * Whitespace handling is only of importance for string-based
20255 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020256 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020257 tmpType = xmlSchemaGetPrimitiveType(type);
20258 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20259 IS_ANY_SIMPLE_TYPE(tmpType)) {
20260 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20261 } else
20262 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20263 /*
20264 * If the value was not computed (for string or
20265 * anySimpleType based types), then use the provided
20266 * type.
20267 */
20268 if (val == NULL)
20269 valType = valType;
20270 else
20271 valType = xmlSchemaGetValType(val);
20272
20273 ret = 0;
20274 for (facetLink = type->facetSet; facetLink != NULL;
20275 facetLink = facetLink->next) {
20276 /*
20277 * Skip the pattern "whiteSpace": it is used to
20278 * format the character content beforehand.
20279 */
20280 switch (facetLink->facet->type) {
20281 case XML_SCHEMA_FACET_WHITESPACE:
20282 case XML_SCHEMA_FACET_PATTERN:
20283 case XML_SCHEMA_FACET_ENUMERATION:
20284 continue;
20285 case XML_SCHEMA_FACET_LENGTH:
20286 case XML_SCHEMA_FACET_MINLENGTH:
20287 case XML_SCHEMA_FACET_MAXLENGTH:
20288 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20289 valType, value, val, &len, ws);
20290 break;
20291 default:
20292 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20293 valType, value, val, ws);
20294 break;
20295 }
20296 if (ret < 0) {
20297 AERROR_INT("xmlSchemaValidateFacets",
20298 "validating against a atomic type facet");
20299 return (-1);
20300 } else if (ret > 0) {
20301 if (fireErrors)
20302 xmlSchemaFacetErr(actxt, ret, node,
20303 value, len, type, facetLink->facet, NULL, NULL, NULL);
20304 else
20305 return (ret);
20306 if (error == 0)
20307 error = ret;
20308 }
20309 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020310 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020311
20312variety_list:
20313 if (! VARIETY_LIST(type))
20314 goto pattern_and_enum;
20315 /*
20316 * "length", "minLength" and "maxLength" of list types.
20317 */
20318 ret = 0;
20319 for (facetLink = type->facetSet; facetLink != NULL;
20320 facetLink = facetLink->next) {
20321
20322 switch (facetLink->facet->type) {
20323 case XML_SCHEMA_FACET_LENGTH:
20324 case XML_SCHEMA_FACET_MINLENGTH:
20325 case XML_SCHEMA_FACET_MAXLENGTH:
20326 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20327 value, length, NULL);
20328 break;
20329 default:
20330 continue;
20331 }
20332 if (ret < 0) {
20333 AERROR_INT("xmlSchemaValidateFacets",
20334 "validating against a list type facet");
20335 return (-1);
20336 } else if (ret > 0) {
20337 if (fireErrors)
20338 xmlSchemaFacetErr(actxt, ret, node,
20339 value, length, type, facetLink->facet, NULL, NULL, NULL);
20340 else
20341 return (ret);
20342 if (error == 0)
20343 error = ret;
20344 }
20345 ret = 0;
20346 }
20347
20348pattern_and_enum:
20349 if (error >= 0) {
20350 int found = 0;
20351 /*
20352 * Process enumerations. Facet values are in the value space
20353 * of the defining type's base type. This seems to be a bug in the
20354 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20355 * Only the first set of enumerations in the ancestor-or-self axis
20356 * is used for validation.
20357 */
20358 ret = 0;
20359 tmpType = type;
20360 do {
20361 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20362 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20363 continue;
20364 found = 1;
20365 ret = xmlSchemaAreValuesEqual(facet->val, val);
20366 if (ret == 1)
20367 break;
20368 else if (ret < 0) {
20369 AERROR_INT("xmlSchemaValidateFacets",
20370 "validating against an enumeration facet");
20371 return (-1);
20372 }
20373 }
20374 if (ret != 0)
20375 break;
20376 tmpType = tmpType->baseType;
20377 } while ((tmpType != NULL) &&
20378 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20379 if (found && (ret == 0)) {
20380 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20381 if (fireErrors) {
20382 xmlSchemaFacetErr(actxt, ret, node,
20383 value, 0, type, NULL, NULL, NULL, NULL);
20384 } else
20385 return (ret);
20386 if (error == 0)
20387 error = ret;
20388 }
20389 }
20390
20391 if (error >= 0) {
20392 int found;
20393 /*
20394 * Process patters. Pattern facets are ORed at type level
20395 * and ANDed if derived. Walk the base type axis.
20396 */
20397 tmpType = type;
20398 facet = NULL;
20399 do {
20400 found = 0;
20401 for (facetLink = tmpType->facetSet; facetLink != NULL;
20402 facetLink = facetLink->next) {
20403 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20404 continue;
20405 found = 1;
20406 /*
20407 * NOTE that for patterns, @value needs to be the
20408 * normalized vaule.
20409 */
20410 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20411 if (ret == 1)
20412 break;
20413 else if (ret < 0) {
20414 AERROR_INT("xmlSchemaValidateFacets",
20415 "validating against a pattern facet");
20416 return (-1);
20417 } else {
20418 /*
20419 * Save the last non-validating facet.
20420 */
20421 facet = facetLink->facet;
20422 }
20423 }
20424 if (found && (ret != 1)) {
20425 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20426 if (fireErrors) {
20427 xmlSchemaFacetErr(actxt, ret, node,
20428 value, 0, type, facet, NULL, NULL, NULL);
20429 } else
20430 return (ret);
20431 if (error == 0)
20432 error = ret;
20433 break;
20434 }
20435 tmpType = tmpType->baseType;
20436 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20437 }
20438
20439 return (error);
20440}
20441
20442static xmlChar *
20443xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20444 const xmlChar *value)
20445{
20446 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20447 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20448 return (xmlSchemaCollapseString(value));
20449 case XML_SCHEMA_WHITESPACE_REPLACE:
20450 return (xmlSchemaWhiteSpaceReplace(value));
20451 default:
20452 return (NULL);
20453 }
20454}
20455
20456static int
20457xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20458 const xmlChar *value,
20459 xmlSchemaValPtr *val,
20460 int valNeeded)
20461{
20462 int ret;
20463 const xmlChar *nsName;
20464 xmlChar *local, *prefix = NULL;
20465
20466 ret = xmlValidateQName(value, 1);
20467 if (ret != 0) {
20468 if (ret == -1) {
20469 VERROR_INT("xmlSchemaValidateQName",
20470 "calling xmlValidateQName()");
20471 return (-1);
20472 }
20473 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20474 }
20475 /*
20476 * NOTE: xmlSplitQName2 will always return a duplicated
20477 * strings.
20478 */
20479 local = xmlSplitQName2(value, &prefix);
20480 if (local == NULL)
20481 local = xmlStrdup(value);
20482 /*
20483 * OPTIMIZE TODO: Use flags for:
20484 * - is there any namespace binding?
20485 * - is there a default namespace?
20486 */
20487 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20488
20489 if (prefix != NULL) {
20490 xmlFree(prefix);
20491 /*
20492 * A namespace must be found if the prefix is
20493 * NOT NULL.
20494 */
20495 if (nsName == NULL) {
20496 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20497 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20498 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20499 "The QName value '%s' has no "
20500 "corresponding namespace declaration in "
20501 "scope", value, NULL);
20502 if (local != NULL)
20503 xmlFree(local);
20504 return (ret);
20505 }
20506 }
20507 if (valNeeded && val) {
20508 if (nsName != NULL)
20509 *val = xmlSchemaNewQNameValue(
20510 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20511 else
20512 *val = xmlSchemaNewQNameValue(NULL,
20513 BAD_CAST local);
20514 } else
20515 xmlFree(local);
20516 return (0);
20517}
20518
20519/*
20520* cvc-simple-type
20521*/
20522static int
20523xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20524 xmlNodePtr node,
20525 xmlSchemaTypePtr type,
20526 const xmlChar *value,
20527 xmlSchemaValPtr *retVal,
20528 int fireErrors,
20529 int normalize,
20530 int isNormalized)
20531{
20532 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20533 xmlSchemaValPtr val = NULL;
20534 xmlSchemaWhitespaceValueType ws;
20535 xmlChar *normValue = NULL;
20536
20537#define NORMALIZE(atype) \
20538 if ((! isNormalized) && \
20539 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20540 normValue = xmlSchemaNormalizeValue(atype, value); \
20541 if (normValue != NULL) \
20542 value = normValue; \
20543 isNormalized = 1; \
20544 }
20545
20546 if ((retVal != NULL) && (*retVal != NULL)) {
20547 xmlSchemaFreeValue(*retVal);
20548 *retVal = NULL;
20549 }
20550 /*
20551 * 3.14.4 Simple Type Definition Validation Rules
20552 * Validation Rule: String Valid
20553 */
20554 /*
20555 * 1 It is schema-valid with respect to that definition as defined
20556 * by Datatype Valid in [XML Schemas: Datatypes].
20557 */
20558 /*
20559 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20560 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20561 * the string must be a ·declared entity name·.
20562 */
20563 /*
20564 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20565 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20566 * then every whitespace-delimited substring of the string must be a ·declared
20567 * entity name·.
20568 */
20569 /*
20570 * 2.3 otherwise no further condition applies.
20571 */
20572 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20573 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020574 if (value == NULL)
20575 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020576 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20577 xmlSchemaTypePtr biType; /* The built-in type. */
20578 /*
20579 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20580 * a literal in the ·lexical space· of {base type definition}"
20581 */
20582 /*
20583 * Whitespace-normalize.
20584 */
20585 NORMALIZE(type);
20586 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20587 /*
20588 * Get the built-in type.
20589 */
20590 biType = type->baseType;
20591 while ((biType != NULL) &&
20592 (biType->type != XML_SCHEMA_TYPE_BASIC))
20593 biType = biType->baseType;
20594
20595 if (biType == NULL) {
20596 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20597 "could not get the built-in type");
20598 goto internal_error;
20599 }
20600 } else
20601 biType = type;
20602 /*
20603 * NOTATIONs need to be processed here, since they need
20604 * to lookup in the hashtable of NOTATION declarations of the schema.
20605 */
20606 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20607 switch (biType->builtInType) {
20608 case XML_SCHEMAS_NOTATION:
20609 ret = xmlSchemaValidateNotation(
20610 (xmlSchemaValidCtxtPtr) actxt,
20611 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20612 NULL, value, &val, valNeeded);
20613 break;
20614 case XML_SCHEMAS_QNAME:
20615 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20616 value, &val, valNeeded);
20617 break;
20618 default:
20619 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20620 if (valNeeded)
20621 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20622 value, &val, NULL);
20623 else
20624 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20625 value, NULL, NULL);
20626 break;
20627 }
20628 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20629 switch (biType->builtInType) {
20630 case XML_SCHEMAS_NOTATION:
20631 ret = xmlSchemaValidateNotation(NULL,
20632 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20633 value, &val, valNeeded);
20634 break;
20635 default:
20636 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20637 if (valNeeded)
20638 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20639 value, &val, node);
20640 else
20641 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20642 value, NULL, node);
20643 break;
20644 }
20645 } else {
20646 /*
20647 * Validation via a public API is not implemented yet.
20648 */
20649 TODO
20650 goto internal_error;
20651 }
20652 if (ret != 0) {
20653 if (ret < 0) {
20654 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20655 "validating against a built-in type");
20656 goto internal_error;
20657 }
20658 if (VARIETY_LIST(type))
20659 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20660 else
20661 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20662 }
20663 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20664 /*
20665 * Check facets.
20666 */
20667 ret = xmlSchemaValidateFacets(actxt, node, type,
20668 (xmlSchemaValType) biType->builtInType, value, val,
20669 0, fireErrors);
20670 if (ret != 0) {
20671 if (ret < 0) {
20672 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20673 "validating facets of atomic simple type");
20674 goto internal_error;
20675 }
20676 if (VARIETY_LIST(type))
20677 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20678 else
20679 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20680 }
20681 }
20682 if (fireErrors && (ret > 0))
20683 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20684 } else if (VARIETY_LIST(type)) {
20685
20686 xmlSchemaTypePtr itemType;
20687 const xmlChar *cur, *end;
20688 xmlChar *tmpValue = NULL;
20689 unsigned long len = 0;
20690 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20691 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20692 * of white space separated tokens, each of which ·match·es a literal
20693 * in the ·lexical space· of {item type definition}
20694 */
20695 /*
20696 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20697 * the list type has an enum or pattern facet.
20698 */
20699 NORMALIZE(type);
20700 /*
20701 * VAL TODO: Optimize validation of empty values.
20702 * VAL TODO: We do not have computed values for lists.
20703 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020704 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020705 cur = value;
20706 do {
20707 while (IS_BLANK_CH(*cur))
20708 cur++;
20709 end = cur;
20710 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20711 end++;
20712 if (end == cur)
20713 break;
20714 tmpValue = xmlStrndup(cur, end - cur);
20715 len++;
20716
20717 if (valNeeded)
20718 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20719 tmpValue, &curVal, fireErrors, 0, 1);
20720 else
20721 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20722 tmpValue, NULL, fireErrors, 0, 1);
20723 FREE_AND_NULL(tmpValue);
20724 if (curVal != NULL) {
20725 /*
20726 * Add to list of computed values.
20727 */
20728 if (val == NULL)
20729 val = curVal;
20730 else
20731 xmlSchemaValueAppend(prevVal, curVal);
20732 prevVal = curVal;
20733 curVal = NULL;
20734 }
20735 if (ret != 0) {
20736 if (ret < 0) {
20737 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20738 "validating an item of list simple type");
20739 goto internal_error;
20740 }
20741 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20742 break;
20743 }
20744 cur = end;
20745 } while (*cur != 0);
20746 FREE_AND_NULL(tmpValue);
20747 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20748 /*
20749 * Apply facets (pattern, enumeration).
20750 */
20751 ret = xmlSchemaValidateFacets(actxt, node, type,
20752 XML_SCHEMAS_UNKNOWN, value, val,
20753 len, fireErrors);
20754 if (ret != 0) {
20755 if (ret < 0) {
20756 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20757 "validating facets of list simple type");
20758 goto internal_error;
20759 }
20760 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20761 }
20762 }
20763 if (fireErrors && (ret > 0)) {
20764 /*
20765 * Report the normalized value.
20766 */
20767 normalize = 1;
20768 NORMALIZE(type);
20769 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20770 }
20771 } else if (VARIETY_UNION(type)) {
20772 xmlSchemaTypeLinkPtr memberLink;
20773 /*
20774 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20775 * not apply directly; however, the normalization behavior of ·union·
20776 * types is controlled by the value of whiteSpace on that one of the
20777 * ·memberTypes· against which the ·union· is successfully validated.
20778 *
20779 * This means that the value is normalized by the first validating
20780 * member type, then the facets of the union type are applied. This
20781 * needs changing of the value!
20782 */
20783
20784 /*
20785 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20786 * literal in the ·lexical space· of at least one member of
20787 * {member type definitions}
20788 */
20789 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20790 if (memberLink == NULL) {
20791 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20792 "union simple type has no member types");
20793 goto internal_error;
20794 }
20795 /*
20796 * Always normalize union type values, since we currently
20797 * cannot store the whitespace information with the value
20798 * itself; otherwise a later value-comparison would be
20799 * not possible.
20800 */
20801 while (memberLink != NULL) {
20802 if (valNeeded)
20803 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20804 memberLink->type, value, &val, 0, 1, 0);
20805 else
20806 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20807 memberLink->type, value, NULL, 0, 1, 0);
20808 if (ret <= 0)
20809 break;
20810 memberLink = memberLink->next;
20811 }
20812 if (ret != 0) {
20813 if (ret < 0) {
20814 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20815 "validating members of union simple type");
20816 goto internal_error;
20817 }
20818 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20819 }
20820 /*
20821 * Apply facets (pattern, enumeration).
20822 */
20823 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20824 /*
20825 * The normalization behavior of ·union· types is controlled by
20826 * the value of whiteSpace on that one of the ·memberTypes·
20827 * against which the ·union· is successfully validated.
20828 */
20829 NORMALIZE(memberLink->type);
20830 ret = xmlSchemaValidateFacets(actxt, node, type,
20831 XML_SCHEMAS_UNKNOWN, value, val,
20832 0, fireErrors);
20833 if (ret != 0) {
20834 if (ret < 0) {
20835 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20836 "validating facets of union simple type");
20837 goto internal_error;
20838 }
20839 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20840 }
20841 }
20842 if (fireErrors && (ret > 0))
20843 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20844 }
20845
20846 if (normValue != NULL)
20847 xmlFree(normValue);
20848 if (ret == 0) {
20849 if (retVal != NULL)
20850 *retVal = val;
20851 else if (val != NULL)
20852 xmlSchemaFreeValue(val);
20853 } else if (val != NULL)
20854 xmlSchemaFreeValue(val);
20855 return (ret);
20856internal_error:
20857 if (normValue != NULL)
20858 xmlFree(normValue);
20859 if (val != NULL)
20860 xmlSchemaFreeValue(val);
20861 return (-1);
20862}
20863
20864static int
20865xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20866 const xmlChar *value,
20867 const xmlChar **nsName,
20868 const xmlChar **localName)
20869{
20870 int ret = 0;
20871
20872 if ((nsName == NULL) || (localName == NULL))
20873 return (-1);
20874 *nsName = NULL;
20875 *localName = NULL;
20876
20877 ret = xmlValidateQName(value, 1);
20878 if (ret == -1)
20879 return (-1);
20880 if (ret > 0) {
20881 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20882 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20883 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20884 return (1);
20885 }
20886 {
20887 xmlChar *local = NULL;
20888 xmlChar *prefix;
20889
20890 /*
20891 * NOTE: xmlSplitQName2 will return a duplicated
20892 * string.
20893 */
20894 local = xmlSplitQName2(value, &prefix);
20895 VAL_CREATE_DICT;
20896 if (local == NULL)
20897 *localName = xmlDictLookup(vctxt->dict, value, -1);
20898 else {
20899 *localName = xmlDictLookup(vctxt->dict, local, -1);
20900 xmlFree(local);
20901 }
20902
20903 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20904
20905 if (prefix != NULL) {
20906 xmlFree(prefix);
20907 /*
20908 * A namespace must be found if the prefix is NOT NULL.
20909 */
20910 if (*nsName == NULL) {
20911 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20912 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20913 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20914 "The QName value '%s' has no "
20915 "corresponding namespace declaration in scope",
20916 value, NULL);
20917 return (2);
20918 }
20919 }
20920 }
20921 return (0);
20922}
20923
20924static int
20925xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20926 xmlSchemaAttrInfoPtr iattr,
20927 xmlSchemaTypePtr *localType,
20928 xmlSchemaElementPtr elemDecl)
20929{
20930 int ret = 0;
20931 /*
20932 * cvc-elt (3.3.4) : (4)
20933 * AND
20934 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20935 * (1.2.1.2.1) - (1.2.1.2.4)
20936 * Handle 'xsi:type'.
20937 */
20938 if (localType == NULL)
20939 return (-1);
20940 *localType = NULL;
20941 if (iattr == NULL)
20942 return (0);
20943 else {
20944 const xmlChar *nsName = NULL, *local = NULL;
20945 /*
20946 * TODO: We should report a *warning* that the type was overriden
20947 * by the instance.
20948 */
20949 ACTIVATE_ATTRIBUTE(iattr);
20950 /*
20951 * (cvc-elt) (3.3.4) : (4.1)
20952 * (cvc-assess-elt) (1.2.1.2.2)
20953 */
20954 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20955 &nsName, &local);
20956 if (ret != 0) {
20957 if (ret < 0) {
20958 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20959 "calling xmlSchemaQNameExpand() to validate the "
20960 "attribute 'xsi:type'");
20961 goto internal_error;
20962 }
20963 goto exit;
20964 }
20965 /*
20966 * (cvc-elt) (3.3.4) : (4.2)
20967 * (cvc-assess-elt) (1.2.1.2.3)
20968 */
20969 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20970 if (*localType == NULL) {
20971 xmlChar *str = NULL;
20972
20973 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20974 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20975 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20976 "The QName value '%s' of the xsi:type attribute does not "
20977 "resolve to a type definition",
20978 xmlSchemaFormatQName(&str, nsName, local), NULL);
20979 FREE_AND_NULL(str);
20980 ret = vctxt->err;
20981 goto exit;
20982 }
20983 if (elemDecl != NULL) {
20984 int set = 0;
20985
20986 /*
20987 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20988 * "The ·local type definition· must be validly
20989 * derived from the {type definition} given the union of
20990 * the {disallowed substitutions} and the {type definition}'s
20991 * {prohibited substitutions}, as defined in
20992 * Type Derivation OK (Complex) (§3.4.6)
20993 * (if it is a complex type definition),
20994 * or given {disallowed substitutions} as defined in Type
20995 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20996 * definition)."
20997 *
20998 * {disallowed substitutions}: the "block" on the element decl.
20999 * {prohibited substitutions}: the "block" on the type def.
21000 */
21001 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21002 (elemDecl->subtypes->flags &
21003 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21004 set |= SUBSET_EXTENSION;
21005
21006 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21007 (elemDecl->subtypes->flags &
21008 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21009 set |= SUBSET_RESTRICTION;
21010
21011 if (xmlSchemaCheckCOSDerivedOK(*localType,
21012 elemDecl->subtypes, set) != 0) {
21013 xmlChar *str = NULL;
21014
21015 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21016 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
21017 "The type definition '%s', specified by xsi:type, is "
21018 "blocked or not validly derived from the type definition "
21019 "of the element declaration",
21020 xmlSchemaFormatQName(&str,
21021 (*localType)->targetNamespace,
21022 (*localType)->name),
21023 NULL);
21024 FREE_AND_NULL(str);
21025 ret = vctxt->err;
21026 *localType = NULL;
21027 }
21028 }
21029 }
21030exit:
21031 ACTIVATE_ELEM;
21032 return (ret);
21033internal_error:
21034 ACTIVATE_ELEM;
21035 return (-1);
21036}
21037
21038static int
21039xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21040{
21041 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21042 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21043
21044 /*
21045 * cvc-elt (3.3.4) : 1
21046 */
21047 if (elemDecl == NULL) {
21048 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21049 "No matching declaration available");
21050 return (vctxt->err);
21051 }
21052 /*
21053 * cvc-elt (3.3.4) : 2
21054 */
21055 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21056 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21057 "The element declaration is abstract");
21058 return (vctxt->err);
21059 }
21060 if (actualType == NULL) {
21061 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21062 "The type definition is absent");
21063 return (XML_SCHEMAV_CVC_TYPE_1);
21064 }
21065 if (vctxt->nbAttrInfos != 0) {
21066 int ret;
21067 xmlSchemaAttrInfoPtr iattr;
21068 /*
21069 * cvc-elt (3.3.4) : 3
21070 * Handle 'xsi:nil'.
21071 */
21072 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21073 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21074 if (iattr) {
21075 ACTIVATE_ATTRIBUTE(iattr);
21076 /*
21077 * Validate the value.
21078 */
21079 ret = xmlSchemaVCheckCVCSimpleType(
21080 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21081 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21082 iattr->value, &(iattr->val), 1, 0, 0);
21083 ACTIVATE_ELEM;
21084 if (ret < 0) {
21085 VERROR_INT("xmlSchemaValidateElemDecl",
21086 "calling xmlSchemaVCheckCVCSimpleType() to "
21087 "validate the attribute 'xsi:nil'");
21088 return (-1);
21089 }
21090 if (ret == 0) {
21091 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21092 /*
21093 * cvc-elt (3.3.4) : 3.1
21094 */
21095 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21096 "The element is not 'nillable'");
21097 /* Does not return an error on purpose. */
21098 } else {
21099 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21100 /*
21101 * cvc-elt (3.3.4) : 3.2.2
21102 */
21103 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21104 (elemDecl->value != NULL)) {
21105 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21106 "The element cannot be 'nilled' because "
21107 "there is a fixed value constraint defined "
21108 "for it");
21109 /* Does not return an error on purpose. */
21110 } else
21111 vctxt->inode->flags |=
21112 XML_SCHEMA_ELEM_INFO_NILLED;
21113 }
21114 }
21115 }
21116 }
21117 /*
21118 * cvc-elt (3.3.4) : 4
21119 * Handle 'xsi:type'.
21120 */
21121 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21122 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21123 if (iattr) {
21124 xmlSchemaTypePtr localType = NULL;
21125
21126 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21127 elemDecl);
21128 if (ret != 0) {
21129 if (ret == -1) {
21130 VERROR_INT("xmlSchemaValidateElemDecl",
21131 "calling xmlSchemaProcessXSIType() to "
21132 "process the attribute 'xsi:type'");
21133 return (-1);
21134 }
21135 /* Does not return an error on purpose. */
21136 }
21137 if (localType != NULL) {
21138 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21139 actualType = localType;
21140 }
21141 }
21142 }
21143 /*
21144 * IDC: Register identity-constraint XPath matchers.
21145 */
21146 if ((elemDecl->idcs != NULL) &&
21147 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21148 return (-1);
21149 /*
21150 * No actual type definition.
21151 */
21152 if (actualType == NULL) {
21153 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21154 "The type definition is absent");
21155 return (XML_SCHEMAV_CVC_TYPE_1);
21156 }
21157 /*
21158 * Remember the actual type definition.
21159 */
21160 vctxt->inode->typeDef = actualType;
21161
21162 return (0);
21163}
21164
21165static int
21166xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21167{
21168 xmlSchemaAttrInfoPtr iattr;
21169 int ret = 0, i;
21170
21171 /*
21172 * SPEC cvc-type (3.1.1)
21173 * "The attributes of must be empty, excepting those whose namespace
21174 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21175 * whose local name is one of type, nil, schemaLocation or
21176 * noNamespaceSchemaLocation."
21177 */
21178 if (vctxt->nbAttrInfos == 0)
21179 return (0);
21180 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21181 iattr = vctxt->attrInfos[i];
21182 if (! iattr->metaType) {
21183 ACTIVATE_ATTRIBUTE(iattr)
21184 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21185 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21186 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21187 }
21188 }
21189 ACTIVATE_ELEM
21190 return (ret);
21191}
21192
21193/*
21194* Cleanup currently used attribute infos.
21195*/
21196static void
21197xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21198{
21199 int i;
21200 xmlSchemaAttrInfoPtr attr;
21201
21202 if (vctxt->nbAttrInfos == 0)
21203 return;
21204 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21205 attr = vctxt->attrInfos[i];
21206 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21207 if (attr->localName != NULL)
21208 xmlFree((xmlChar *) attr->localName);
21209 if (attr->nsName != NULL)
21210 xmlFree((xmlChar *) attr->nsName);
21211 }
21212 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21213 if (attr->value != NULL)
21214 xmlFree((xmlChar *) attr->value);
21215 }
21216 if (attr->val != NULL) {
21217 xmlSchemaFreeValue(attr->val);
21218 attr->val = NULL;
21219 }
21220 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21221 }
21222 vctxt->nbAttrInfos = 0;
21223}
21224
21225/*
21226* 3.4.4 Complex Type Definition Validation Rules
21227* Element Locally Valid (Complex Type) (cvc-complex-type)
21228* 3.2.4 Attribute Declaration Validation Rules
21229* Validation Rule: Attribute Locally Valid (cvc-attribute)
21230* Attribute Locally Valid (Use) (cvc-au)
21231*
21232* Only "assessed" attribute information items will be visible to
21233* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21234*/
21235static int
21236xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21237{
21238 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21239 xmlSchemaAttributeLinkPtr attrUseLink;
21240 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21241 xmlSchemaAttrInfoPtr attr, tmpAttr;
21242 int i, found, nbAttrs;
21243 int xpathRes = 0, res, wildIDs = 0, fixed;
21244
21245 /*
21246 * SPEC (cvc-attribute)
21247 * (1) "The declaration must not be ·absent· (see Missing
21248 * Sub-components (§5.3) for how this can fail to be
21249 * the case)."
21250 * (2) "Its {type definition} must not be absent."
21251 *
21252 * NOTE (1) + (2): This is not handled here, since we currently do not
21253 * allow validation against schemas which have missing sub-components.
21254 *
21255 * SPEC (cvc-complex-type)
21256 * (3) "For each attribute information item in the element information
21257 * item's [attributes] excepting those whose [namespace name] is
21258 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21259 * [local name] is one of type, nil, schemaLocation or
21260 * noNamespaceSchemaLocation, the appropriate case among the following
21261 * must be true:
21262 *
21263 */
21264 nbAttrs = vctxt->nbAttrInfos;
21265 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21266 attrUseLink = attrUseLink->next) {
21267
21268 found = 0;
21269 attrUse = attrUseLink->attr;
21270 /*
21271 * VAL TODO: Implement a real "attribute use" component.
21272 */
21273 if (attrUse->refDecl != NULL)
21274 attrDecl = attrUse->refDecl;
21275 else
21276 attrDecl = attrUse;
21277 for (i = 0; i < nbAttrs; i++) {
21278 attr = vctxt->attrInfos[i];
21279 /*
21280 * SPEC (cvc-complex-type) (3)
21281 * Skip meta attributes.
21282 */
21283 if (attr->metaType)
21284 continue;
21285 if (attr->localName[0] != attrDecl->name[0])
21286 continue;
21287 if (!xmlStrEqual(attr->localName, attrDecl->name))
21288 continue;
21289 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21290 continue;
21291 found = 1;
21292 /*
21293 * SPEC (cvc-complex-type)
21294 * (3.1) "If there is among the {attribute uses} an attribute
21295 * use with an {attribute declaration} whose {name} matches
21296 * the attribute information item's [local name] and whose
21297 * {target namespace} is identical to the attribute information
21298 * item's [namespace name] (where an ·absent· {target namespace}
21299 * is taken to be identical to a [namespace name] with no value),
21300 * then the attribute information must be ·valid· with respect
21301 * to that attribute use as per Attribute Locally Valid (Use)
21302 * (§3.5.4). In this case the {attribute declaration} of that
21303 * attribute use is the ·context-determined declaration· for the
21304 * attribute information item with respect to Schema-Validity
21305 * Assessment (Attribute) (§3.2.4) and
21306 * Assessment Outcome (Attribute) (§3.2.5).
21307 */
21308 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21309 attr->use = attrUse;
21310 /*
21311 * Context-determined declaration.
21312 */
21313 attr->decl = attrDecl;
21314 attr->typeDef = attrDecl->subtypes;
21315 break;
21316 }
21317
21318 if (found)
21319 continue;
21320
21321 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21322 /*
21323 * Handle non-existent, required attributes.
21324 *
21325 * SPEC (cvc-complex-type)
21326 * (4) "The {attribute declaration} of each attribute use in
21327 * the {attribute uses} whose {required} is true matches one
21328 * of the attribute information items in the element information
21329 * item's [attributes] as per clause 3.1 above."
21330 */
21331 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21332 if (tmpAttr == NULL) {
21333 VERROR_INT(
21334 "xmlSchemaVAttributesComplex",
21335 "calling xmlSchemaGetFreshAttrInfo()");
21336 return (-1);
21337 }
21338 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21339 tmpAttr->use = attrUse;
21340 tmpAttr->decl = attrDecl;
21341 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21342 ((attrUse->defValue != NULL) ||
21343 (attrDecl->defValue != NULL))) {
21344 /*
21345 * Handle non-existent, optional, default/fixed attributes.
21346 */
21347 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21348 if (tmpAttr == NULL) {
21349 VERROR_INT(
21350 "xmlSchemaVAttributesComplex",
21351 "calling xmlSchemaGetFreshAttrInfo()");
21352 return (-1);
21353 }
21354 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21355 tmpAttr->use = attrUse;
21356 tmpAttr->decl = attrDecl;
21357 tmpAttr->typeDef = attrDecl->subtypes;
21358 tmpAttr->localName = attrDecl->name;
21359 tmpAttr->nsName = attrDecl->targetNamespace;
21360 }
21361 }
21362 if (vctxt->nbAttrInfos == 0)
21363 return (0);
21364 /*
21365 * Validate against the wildcard.
21366 */
21367 if (type->attributeWildcard != NULL) {
21368 /*
21369 * SPEC (cvc-complex-type)
21370 * (3.2.1) "There must be an {attribute wildcard}."
21371 */
21372 for (i = 0; i < nbAttrs; i++) {
21373 attr = vctxt->attrInfos[i];
21374 /*
21375 * SPEC (cvc-complex-type) (3)
21376 * Skip meta attributes.
21377 */
21378 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21379 continue;
21380 /*
21381 * SPEC (cvc-complex-type)
21382 * (3.2.2) "The attribute information item must be ·valid· with
21383 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21384 *
21385 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21386 * "... its [namespace name] must be ·valid· with respect to
21387 * the wildcard constraint, as defined in Wildcard allows
21388 * Namespace Name (§3.10.4)."
21389 */
21390 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21391 attr->nsName)) {
21392 /*
21393 * Handle processContents.
21394 *
21395 * SPEC (cvc-wildcard):
21396 * processContents | context-determined declaration:
21397 * "strict" "mustFind"
21398 * "lax" "none"
21399 * "skip" "skip"
21400 */
21401 if (type->attributeWildcard->processContents ==
21402 XML_SCHEMAS_ANY_SKIP) {
21403 /*
21404 * context-determined declaration = "skip"
21405 *
21406 * SPEC PSVI Assessment Outcome (Attribute)
21407 * [validity] = "notKnown"
21408 * [validation attempted] = "none"
21409 */
21410 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21411 continue;
21412 }
21413 /*
21414 * Find an attribute declaration.
21415 */
21416 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21417 attr->localName, attr->nsName);
21418 if (attr->decl != NULL) {
21419 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21420 /*
21421 * SPEC (cvc-complex-type)
21422 * (5) "Let [Definition:] the wild IDs be the set of
21423 * all attribute information item to which clause 3.2
21424 * applied and whose ·validation· resulted in a
21425 * ·context-determined declaration· of mustFind or no
21426 * ·context-determined declaration· at all, and whose
21427 * [local name] and [namespace name] resolve (as
21428 * defined by QName resolution (Instance) (§3.15.4)) to
21429 * an attribute declaration whose {type definition} is
21430 * or is derived from ID. Then all of the following
21431 * must be true:"
21432 */
21433 attr->typeDef = attr->decl->subtypes;
21434 if (xmlSchemaIsDerivedFromBuiltInType(
21435 attr->typeDef, XML_SCHEMAS_ID)) {
21436 /*
21437 * SPEC (5.1) "There must be no more than one
21438 * item in ·wild IDs·."
21439 */
21440 if (wildIDs != 0) {
21441 /* VAL TODO */
21442 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21443 TODO
21444 continue;
21445 }
21446 wildIDs++;
21447 /*
21448 * SPEC (cvc-complex-type)
21449 * (5.2) "If ·wild IDs· is non-empty, there must not
21450 * be any attribute uses among the {attribute uses}
21451 * whose {attribute declaration}'s {type definition}
21452 * is or is derived from ID."
21453 */
21454 for (attrUseLink = type->attributeUses;
21455 attrUseLink != NULL;
21456 attrUseLink = attrUseLink->next) {
21457 if (xmlSchemaIsDerivedFromBuiltInType(
21458 attrUseLink->attr->subtypes,
21459 XML_SCHEMAS_ID)) {
21460 /* VAL TODO */
21461 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21462 TODO
21463 }
21464 }
21465 }
21466 } else if (type->attributeWildcard->processContents ==
21467 XML_SCHEMAS_ANY_LAX) {
21468 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21469 /*
21470 * SPEC PSVI Assessment Outcome (Attribute)
21471 * [validity] = "notKnown"
21472 * [validation attempted] = "none"
21473 */
21474 } else {
21475 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21476 }
21477 }
21478 }
21479 }
21480
21481
21482 if (vctxt->nbAttrInfos == 0)
21483 return (0);
21484
21485 /*
21486 * Validate values, create default attributes, evaluate IDCs.
21487 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021488 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21489 attr = vctxt->attrInfos[i];
21490 /*
21491 * VAL TODO: Note that we won't try to resolve IDCs to
21492 * "lax" and "skip" validated attributes. Check what to
21493 * do in this case.
21494 */
21495 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21496 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21497 continue;
21498 /*
21499 * VAL TODO: What to do if the type definition is missing?
21500 */
21501 if (attr->typeDef == NULL) {
21502 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21503 continue;
21504 }
21505
21506 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021507 fixed = 0;
21508 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021509
21510 if (vctxt->xpathStates != NULL) {
21511 /*
21512 * Evaluate IDCs.
21513 */
21514 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21515 XML_ATTRIBUTE_NODE);
21516 if (xpathRes == -1) {
21517 VERROR_INT("xmlSchemaVAttributesComplex",
21518 "calling xmlSchemaXPathEvaluate()");
21519 goto internal_error;
21520 }
21521 }
21522
21523 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21524 /*
21525 * Default/fixed attributes.
21526 */
21527 if (xpathRes) {
21528 if (attr->use->defValue == NULL) {
21529 attr->value = (xmlChar *) attr->use->defValue;
21530 attr->val = attr->use->defVal;
21531 } else {
21532 attr->value = (xmlChar *) attr->decl->defValue;
21533 attr->val = attr->decl->defVal;
21534 }
21535 /*
21536 * IDCs will consume the precomputed default value,
21537 * so we need to clone it.
21538 */
21539 if (attr->val == NULL) {
21540 VERROR_INT("xmlSchemaVAttributesComplex",
21541 "default/fixed value on an attribute use was "
21542 "not precomputed");
21543 goto internal_error;
21544 }
21545 attr->val = xmlSchemaCopyValue(attr->val);
21546 if (attr->val == NULL) {
21547 VERROR_INT("xmlSchemaVAttributesComplex",
21548 "calling xmlSchemaCopyValue()");
21549 goto internal_error;
21550 }
21551 }
21552 /*
21553 * PSVI: Add the default attribute to the current element.
21554 * VAL TODO: Should we use the *normalized* value? This currently
21555 * uses the *initial* value.
21556 */
21557 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21558 (attr->node != NULL) && (attr->node->doc != NULL)) {
21559 xmlChar *normValue;
21560 const xmlChar *value;
21561
21562 value = attr->value;
21563 /*
21564 * Normalize the value.
21565 */
21566 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21567 attr->value);
21568 if (normValue != NULL)
21569 value = BAD_CAST normValue;
21570
21571 if (attr->nsName == NULL) {
21572 if (xmlNewProp(attr->node->parent,
21573 attr->localName, value) == NULL) {
21574 VERROR_INT("xmlSchemaVAttributesComplex",
21575 "callling xmlNewProp()");
21576 if (normValue != NULL)
21577 xmlFree(normValue);
21578 goto internal_error;
21579 }
21580 } else {
21581 xmlNsPtr ns;
21582
21583 ns = xmlSearchNsByHref(attr->node->doc,
21584 attr->node->parent, attr->nsName);
21585 if (ns == NULL) {
21586 xmlChar prefix[12];
21587 int counter = 0;
21588
21589 /*
21590 * Create a namespace declaration on the validation
21591 * root node if no namespace declaration is in scope.
21592 */
21593 do {
21594 snprintf((char *) prefix, 12, "p%d", counter++);
21595 ns = xmlSearchNs(attr->node->doc,
21596 attr->node->parent, BAD_CAST prefix);
21597 if (counter > 1000) {
21598 VERROR_INT(
21599 "xmlSchemaVAttributesComplex",
21600 "could not compute a ns prefix for a "
21601 "default/fixed attribute");
21602 if (normValue != NULL)
21603 xmlFree(normValue);
21604 goto internal_error;
21605 }
21606 } while (ns != NULL);
21607 ns = xmlNewNs(vctxt->validationRoot,
21608 attr->nsName, BAD_CAST prefix);
21609 }
21610 xmlNewNsProp(attr->node->parent, ns,
21611 attr->localName, value);
21612 }
21613 if (normValue != NULL)
21614 xmlFree(normValue);
21615 }
21616 /*
21617 * Go directly to IDC evaluation.
21618 */
21619 goto eval_idcs;
21620 }
21621 /*
21622 * Validate the value.
21623 */
21624 if (vctxt->value != NULL) {
21625 /*
21626 * Free last computed value; just for safety reasons.
21627 */
21628 xmlSchemaFreeValue(vctxt->value);
21629 vctxt->value = NULL;
21630 }
21631 /*
21632 * Note that the attribute *use* can be unavailable, if
21633 * the attribute was a wild attribute.
21634 */
21635 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21636 ((attr->use != NULL) &&
21637 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21638 fixed = 1;
21639 else
21640 fixed = 0;
21641 /*
21642 * SPEC (cvc-attribute)
21643 * (3) "The item's ·normalized value· must be locally ·valid·
21644 * with respect to that {type definition} as per
21645 * String Valid (§3.14.4)."
21646 *
21647 * VAL TODO: Do we already have the
21648 * "normalized attribute value" here?
21649 */
21650 if (xpathRes || fixed) {
21651 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21652 /*
21653 * Request a computed value.
21654 */
21655 res = xmlSchemaVCheckCVCSimpleType(
21656 (xmlSchemaAbstractCtxtPtr) vctxt,
21657 attr->node, attr->typeDef, attr->value, &(attr->val),
21658 1, 1, 0);
21659 } else {
21660 res = xmlSchemaVCheckCVCSimpleType(
21661 (xmlSchemaAbstractCtxtPtr) vctxt,
21662 attr->node, attr->typeDef, attr->value, NULL,
21663 1, 0, 0);
21664 }
21665
21666 if (res != 0) {
21667 if (res == -1) {
21668 VERROR_INT("xmlSchemaVAttributesComplex",
21669 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21670 goto internal_error;
21671 }
21672 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21673 /*
21674 * SPEC PSVI Assessment Outcome (Attribute)
21675 * [validity] = "invalid"
21676 */
21677 goto eval_idcs;
21678 }
21679
21680 if (fixed) {
21681 int ws;
21682 /*
21683 * SPEC Attribute Locally Valid (Use) (cvc-au)
21684 * "For an attribute information item to be·valid·
21685 * with respect to an attribute use its *normalized*
21686 * value· must match the *canonical* lexical
21687 * representation of the attribute use's {value
21688 * constraint}value, if it is present and fixed."
21689 *
21690 * VAL TODO: The requirement for the *canonical* value
21691 * will be removed in XML Schema 1.1.
21692 */
21693 /*
21694 * SPEC Attribute Locally Valid (cvc-attribute)
21695 * (4) "The item's *actual* value· must match the *value* of
21696 * the {value constraint}, if it is present and fixed."
21697 */
21698 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21699 if (attr->val == NULL) {
21700 /* VAL TODO: A value was not precomputed. */
21701 TODO
21702 goto eval_idcs;
21703 }
21704 if ((attr->use != NULL) &&
21705 (attr->use->defValue != NULL)) {
21706 if (attr->use->defVal == NULL) {
21707 /* VAL TODO: A default value was not precomputed. */
21708 TODO
21709 goto eval_idcs;
21710 }
21711 attr->vcValue = attr->use->defValue;
21712 /*
21713 if (xmlSchemaCompareValuesWhtsp(attr->val,
21714 (xmlSchemaWhitespaceValueType) ws,
21715 attr->use->defVal,
21716 (xmlSchemaWhitespaceValueType) ws) != 0) {
21717 */
21718 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21719 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21720 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021721 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021722 /* VAL TODO: A default value was not precomputed. */
21723 TODO
21724 goto eval_idcs;
21725 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021726 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021727 /*
21728 if (xmlSchemaCompareValuesWhtsp(attr->val,
21729 (xmlSchemaWhitespaceValueType) ws,
21730 attrDecl->defVal,
21731 (xmlSchemaWhitespaceValueType) ws) != 0) {
21732 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021733 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021734 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21735 }
21736 /*
21737 * [validity] = "valid"
21738 */
21739 }
21740eval_idcs:
21741 /*
21742 * Evaluate IDCs.
21743 */
21744 if (xpathRes) {
21745 if (xmlSchemaXPathProcessHistory(vctxt,
21746 vctxt->depth +1) == -1) {
21747 VERROR_INT("xmlSchemaVAttributesComplex",
21748 "calling xmlSchemaXPathEvaluate()");
21749 goto internal_error;
21750 }
21751 }
21752 }
21753
21754 /*
21755 * Report errors.
21756 */
21757 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21758 attr = vctxt->attrInfos[i];
21759 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21760 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21761 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21762 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21763 continue;
21764 ACTIVATE_ATTRIBUTE(attr);
21765 switch (attr->state) {
21766 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21767 xmlChar *str = NULL;
21768 ACTIVATE_ELEM;
21769 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21770 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21771 "The attribute '%s' is required but missing",
21772 xmlSchemaFormatQName(&str,
21773 attr->decl->targetNamespace,
21774 attr->decl->name),
21775 NULL);
21776 FREE_AND_NULL(str)
21777 break;
21778 }
21779 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21780 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21781 "The type definition is absent");
21782 break;
21783 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21784 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21785 XML_SCHEMAV_CVC_AU, NULL, NULL,
21786 "The value '%s' does not match the fixed "
21787 "value constraint '%s'",
21788 attr->value, attr->vcValue);
21789 break;
21790 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21791 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21792 "No matching global attribute declaration available, but "
21793 "demanded by the strict wildcard");
21794 break;
21795 case XML_SCHEMAS_ATTR_UNKNOWN:
21796 if (attr->metaType)
21797 break;
21798 /*
21799 * MAYBE VAL TODO: One might report different error messages
21800 * for the following errors.
21801 */
21802 if (type->attributeWildcard == NULL) {
21803 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21804 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21805 } else {
21806 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21807 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21808 }
21809 break;
21810 default:
21811 break;
21812 }
21813 }
21814
21815 ACTIVATE_ELEM;
21816 return (0);
21817internal_error:
21818 ACTIVATE_ELEM;
21819 return (-1);
21820}
21821
21822static int
21823xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21824 int *skip)
21825{
21826 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21827 /*
21828 * The namespace of the element was already identified to be
21829 * matching the wildcard.
21830 */
21831 if ((skip == NULL) || (wild == NULL) ||
21832 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21833 VERROR_INT("xmlSchemaValidateElemWildcard",
21834 "bad arguments");
21835 return (-1);
21836 }
21837 *skip = 0;
21838 if (wild->negNsSet != NULL) {
21839 /*
21840 * URGENT VAL TODO: Fix the content model to reject
21841 * "##other" wildcards.
21842 */
21843 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21844 vctxt->inode->nsName) != 0) {
21845 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21846 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21847 /*
21848 * VAL TODO: Workaround possible *only* if minOccurs and
21849 * maxOccurs are 1.
21850 */
21851 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21852 /* VAL TODO: error code? */
21853 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21854 (xmlSchemaTypePtr) wild,
21855 "This element is not accepted by the wildcard",
21856 0, 0, NULL);
21857 vctxt->skipDepth = vctxt->depth;
21858 if ((pinode->flags &
21859 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21860 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21861 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21862 return (XML_SCHEMAV_ELEMENT_CONTENT);
21863 }
21864 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21865 *skip = 1;
21866 return (0);
21867 }
21868 vctxt->inode->typeDef =
21869 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21870 return (0);
21871 }
21872 }
21873 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21874 /*
21875 * URGENT VAL TODO: Either we need to position the stream to the
21876 * next sibling, or walk the whole subtree.
21877 */
21878 *skip = 1;
21879 return (0);
21880 }
21881 {
21882 xmlSchemaElementPtr decl = NULL;
21883
21884 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21885 vctxt->inode->localName, vctxt->inode->nsName,
21886 NULL);
21887 if (decl != NULL) {
21888 vctxt->inode->decl = decl;
21889 return (0);
21890 }
21891 }
21892 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21893 /* VAL TODO: Change to proper error code. */
21894 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21895 "No matching global element declaration available, but "
21896 "demanded by the strict wildcard");
21897 return (vctxt->err);
21898 }
21899 if (vctxt->nbAttrInfos != 0) {
21900 xmlSchemaAttrInfoPtr iattr;
21901 /*
21902 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21903 * (1.2.1.2.1) - (1.2.1.2.3 )
21904 *
21905 * Use the xsi:type attribute for the type definition.
21906 */
21907 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21908 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21909 if (iattr != NULL) {
21910 if (xmlSchemaProcessXSIType(vctxt, iattr,
21911 &(vctxt->inode->typeDef), NULL) == -1) {
21912 VERROR_INT("xmlSchemaValidateElemWildcard",
21913 "calling xmlSchemaProcessXSIType() to "
21914 "process the attribute 'xsi:nil'");
21915 return (-1);
21916 }
21917 /*
21918 * Don't return an error on purpose.
21919 */
21920 return (0);
21921 }
21922 }
21923 /*
21924 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21925 *
21926 * Fallback to "anyType".
21927 */
21928 vctxt->inode->typeDef =
21929 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21930 return (0);
21931}
21932
21933/*
21934* xmlSchemaCheckCOSValidDefault:
21935*
21936* This will be called if: not nilled, no content and a default/fixed
21937* value is provided.
21938*/
21939
21940static int
21941xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21942 const xmlChar *value,
21943 xmlSchemaValPtr *val)
21944{
21945 int ret = 0;
21946 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21947
21948 /*
21949 * cos-valid-default:
21950 * Schema Component Constraint: Element Default Valid (Immediate)
21951 * For a string to be a valid default with respect to a type
21952 * definition the appropriate case among the following must be true:
21953 */
21954 if IS_COMPLEX_TYPE(inode->typeDef) {
21955 /*
21956 * Complex type.
21957 *
21958 * SPEC (2.1) "its {content type} must be a simple type definition
21959 * or mixed."
21960 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21961 * type}'s particle must be ·emptiable· as defined by
21962 * Particle Emptiable (§3.9.6)."
21963 */
21964 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21965 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21966 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21967 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21968 /* NOTE that this covers (2.2.2) as well. */
21969 VERROR(ret, NULL,
21970 "For a string to be a valid default, the type definition "
21971 "must be a simple type or a complex type with simple content "
21972 "or mixed content and a particle emptiable");
21973 return(ret);
21974 }
21975 }
21976 /*
21977 * 1 If the type definition is a simple type definition, then the string
21978 * must be ·valid· with respect to that definition as defined by String
21979 * Valid (§3.14.4).
21980 *
21981 * AND
21982 *
21983 * 2.2.1 If the {content type} is a simple type definition, then the
21984 * string must be ·valid· with respect to that simple type definition
21985 * as defined by String Valid (§3.14.4).
21986 */
21987 if (IS_SIMPLE_TYPE(inode->typeDef)) {
21988
21989 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21990 NULL, inode->typeDef, value, val, 1, 1, 0);
21991
21992 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
21993
21994 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21995 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
21996 }
21997 if (ret < 0) {
21998 VERROR_INT("xmlSchemaCheckCOSValidDefault",
21999 "calling xmlSchemaVCheckCVCSimpleType()");
22000 }
22001 return (ret);
22002}
22003
22004static void
22005xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22006 const xmlChar * name ATTRIBUTE_UNUSED,
22007 xmlSchemaElementPtr item,
22008 xmlSchemaNodeInfoPtr inode)
22009{
22010 inode->decl = item;
22011#ifdef DEBUG_CONTENT
22012 {
22013 xmlChar *str = NULL;
22014
22015 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
22016 xmlGenericError(xmlGenericErrorContext,
22017 "AUTOMATON callback for '%s' [declaration]\n",
22018 xmlSchemaFormatQName(&str,
22019 inode->localName, inode->nsName));
22020 } else {
22021 xmlGenericError(xmlGenericErrorContext,
22022 "AUTOMATON callback for '%s' [wildcard]\n",
22023 xmlSchemaFormatQName(&str,
22024 inode->localName, inode->nsName));
22025
22026 }
22027 FREE_AND_NULL(str)
22028 }
22029#endif
22030}
22031
22032static int
22033xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022034{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022035 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22036 if (vctxt->inode == NULL) {
22037 VERROR_INT("xmlSchemaValidatorPushElem",
22038 "calling xmlSchemaGetFreshElemInfo()");
22039 return (-1);
22040 }
22041 vctxt->nbAttrInfos = 0;
22042 return (0);
22043}
22044
22045static int
22046xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22047 xmlSchemaNodeInfoPtr inode,
22048 xmlSchemaTypePtr type,
22049 const xmlChar *value)
22050{
22051 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22052 return (xmlSchemaVCheckCVCSimpleType(
22053 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22054 type, value, &(inode->val), 1, 1, 0));
22055 else
22056 return (xmlSchemaVCheckCVCSimpleType(
22057 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22058 type, value, NULL, 1, 0, 0));
22059}
22060
22061
22062
22063/*
22064* Process END of element.
22065*/
22066static int
22067xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22068{
22069 int ret = 0;
22070 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22071
22072 if (vctxt->nbAttrInfos != 0)
22073 xmlSchemaClearAttrInfos(vctxt);
22074 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22075 /*
22076 * This element was not expected;
22077 * we will not validate child elements of broken parents.
22078 * Skip validation of all content of the parent.
22079 */
22080 vctxt->skipDepth = vctxt->depth -1;
22081 goto end_elem;
22082 }
22083 if ((inode->typeDef == NULL) ||
22084 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22085 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022086 * 1. the type definition might be missing if the element was
22087 * error prone
22088 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022089 */
22090 goto end_elem;
22091 }
22092 /*
22093 * Check the content model.
22094 */
22095 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22096 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22097
22098 /*
22099 * Workaround for "anyType".
22100 */
22101 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22102 goto character_content;
22103
22104 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22105 xmlChar *values[10];
22106 int terminal, nbval = 10, nbneg;
22107
22108 if (inode->regexCtxt == NULL) {
22109 /*
22110 * Create the regex context.
22111 */
22112 inode->regexCtxt =
22113 xmlRegNewExecCtxt(inode->typeDef->contModel,
22114 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22115 vctxt);
22116 if (inode->regexCtxt == NULL) {
22117 VERROR_INT("xmlSchemaValidatorPopElem",
22118 "failed to create a regex context");
22119 goto internal_error;
22120 }
22121#ifdef DEBUG_AUTOMATA
22122 xmlGenericError(xmlGenericErrorContext,
22123 "AUTOMATON create on '%s'\n", inode->localName);
22124#endif
22125 }
22126 /*
22127 * Get hold of the still expected content, since a further
22128 * call to xmlRegExecPushString() will loose this information.
22129 */
22130 xmlRegExecNextValues(inode->regexCtxt,
22131 &nbval, &nbneg, &values[0], &terminal);
22132 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22133 if (ret <= 0) {
22134 /*
22135 * Still missing something.
22136 */
22137 ret = 1;
22138 inode->flags |=
22139 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22140 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22141 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22142 "Missing child element(s)",
22143 nbval, nbneg, values);
22144#ifdef DEBUG_AUTOMATA
22145 xmlGenericError(xmlGenericErrorContext,
22146 "AUTOMATON missing ERROR on '%s'\n",
22147 inode->localName);
22148#endif
22149 } else {
22150 /*
22151 * Content model is satisfied.
22152 */
22153 ret = 0;
22154#ifdef DEBUG_AUTOMATA
22155 xmlGenericError(xmlGenericErrorContext,
22156 "AUTOMATON succeeded on '%s'\n",
22157 inode->localName);
22158#endif
22159 }
22160
22161 }
22162 }
22163 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22164 goto end_elem;
22165
22166character_content:
22167
22168 if (vctxt->value != NULL) {
22169 xmlSchemaFreeValue(vctxt->value);
22170 vctxt->value = NULL;
22171 }
22172 /*
22173 * Check character content.
22174 */
22175 if (inode->decl == NULL) {
22176 /*
22177 * Speedup if no declaration exists.
22178 */
22179 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22180 ret = xmlSchemaVCheckINodeDataType(vctxt,
22181 inode, inode->typeDef, inode->value);
22182 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22183 ret = xmlSchemaVCheckINodeDataType(vctxt,
22184 inode, inode->typeDef->contentTypeDef,
22185 inode->value);
22186 }
22187 if (ret < 0) {
22188 VERROR_INT("xmlSchemaValidatorPopElem",
22189 "calling xmlSchemaVCheckCVCSimpleType()");
22190 goto internal_error;
22191 }
22192 goto end_elem;
22193 }
22194 /*
22195 * cvc-elt (3.3.4) : 5
22196 * The appropriate case among the following must be true:
22197 */
22198 /*
22199 * cvc-elt (3.3.4) : 5.1
22200 * If the declaration has a {value constraint},
22201 * the item has neither element nor character [children] and
22202 * clause 3.2 has not applied, then all of the following must be true:
22203 */
22204 if ((inode->decl->value != NULL) &&
22205 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22206 (! INODE_NILLED(inode))) {
22207 /*
22208 * cvc-elt (3.3.4) : 5.1.1
22209 * If the ·actual type definition· is a ·local type definition·
22210 * then the canonical lexical representation of the {value constraint}
22211 * value must be a valid default for the ·actual type definition· as
22212 * defined in Element Default Valid (Immediate) (§3.3.6).
22213 */
22214 /*
22215 * NOTE: 'local' above means types aquired by xsi:type.
22216 * NOTE: Although the *canonical* value is stated, it is not
22217 * relevant if canonical or not. Additionally XML Schema 1.1
22218 * will removed this requirement as well.
22219 */
22220 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22221
22222 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22223 inode->decl->value, &(inode->val));
22224 if (ret != 0) {
22225 if (ret < 0) {
22226 VERROR_INT("xmlSchemaValidatorPopElem",
22227 "calling xmlSchemaCheckCOSValidDefault()");
22228 goto internal_error;
22229 }
22230 goto end_elem;
22231 }
22232 /*
22233 * Stop here, to avoid redundant validation of the value
22234 * (see following).
22235 */
22236 goto default_psvi;
22237 }
22238 /*
22239 * cvc-elt (3.3.4) : 5.1.2
22240 * The element information item with the canonical lexical
22241 * representation of the {value constraint} value used as its
22242 * ·normalized value· must be ·valid· with respect to the
22243 * ·actual type definition· as defined by Element Locally Valid (Type)
22244 * (§3.3.4).
22245 */
22246 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22247 ret = xmlSchemaVCheckINodeDataType(vctxt,
22248 inode, inode->typeDef, inode->decl->value);
22249 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22250 ret = xmlSchemaVCheckINodeDataType(vctxt,
22251 inode, inode->typeDef->contentTypeDef,
22252 inode->decl->value);
22253 }
22254 if (ret != 0) {
22255 if (ret < 0) {
22256 VERROR_INT("xmlSchemaValidatorPopElem",
22257 "calling xmlSchemaVCheckCVCSimpleType()");
22258 goto internal_error;
22259 }
22260 goto end_elem;
22261 }
22262
22263default_psvi:
22264 /*
22265 * PSVI: Create a text node on the instance element.
22266 */
22267 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22268 (inode->node != NULL)) {
22269 xmlNodePtr textChild;
22270 xmlChar *normValue;
22271 /*
22272 * VAL TODO: Normalize the value.
22273 */
22274 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22275 inode->decl->value);
22276 if (normValue != NULL) {
22277 textChild = xmlNewText(BAD_CAST normValue);
22278 xmlFree(normValue);
22279 } else
22280 textChild = xmlNewText(inode->decl->value);
22281 if (textChild == NULL) {
22282 VERROR_INT("xmlSchemaValidatorPopElem",
22283 "calling xmlNewText()");
22284 goto internal_error;
22285 } else
22286 xmlAddChild(inode->node, textChild);
22287 }
22288
22289 } else if (! INODE_NILLED(inode)) {
22290 /*
22291 * 5.2.1 The element information item must be ·valid· with respect
22292 * to the ·actual type definition· as defined by Element Locally
22293 * Valid (Type) (§3.3.4).
22294 */
22295 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22296 /*
22297 * SPEC (cvc-type) (3.1)
22298 * "If the type definition is a simple type definition, ..."
22299 * (3.1.3) "If clause 3.2 of Element Locally Valid
22300 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22301 * must be ·valid· with respect to the type definition as defined
22302 * by String Valid (§3.14.4).
22303 */
22304 ret = xmlSchemaVCheckINodeDataType(vctxt,
22305 inode, inode->typeDef, inode->value);
22306 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22307 /*
22308 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22309 * definition, then the element information item must be
22310 * ·valid· with respect to the type definition as per
22311 * Element Locally Valid (Complex Type) (§3.4.4);"
22312 *
22313 * SPEC (cvc-complex-type) (2.2)
22314 * "If the {content type} is a simple type definition, ...
22315 * the ·normalized value· of the element information item is
22316 * ·valid· with respect to that simple type definition as
22317 * defined by String Valid (§3.14.4)."
22318 */
22319 ret = xmlSchemaVCheckINodeDataType(vctxt,
22320 inode, inode->typeDef->contentTypeDef, inode->value);
22321 }
22322 if (ret != 0) {
22323 if (ret < 0) {
22324 VERROR_INT("xmlSchemaValidatorPopElem",
22325 "calling xmlSchemaVCheckCVCSimpleType()");
22326 goto internal_error;
22327 }
22328 goto end_elem;
22329 }
22330 /*
22331 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22332 * not applied, all of the following must be true:
22333 */
22334 if ((inode->decl->value != NULL) &&
22335 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22336
22337 /*
22338 * TODO: We will need a computed value, when comparison is
22339 * done on computed values.
22340 */
22341 /*
22342 * 5.2.2.1 The element information item must have no element
22343 * information item [children].
22344 */
22345 if (inode->flags &
22346 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22347 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22348 VERROR(ret, NULL,
22349 "The content must not containt element nodes since "
22350 "there is a fixed value constraint");
22351 goto end_elem;
22352 } else {
22353 /*
22354 * 5.2.2.2 The appropriate case among the following must
22355 * be true:
22356 */
22357 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22358 /*
22359 * 5.2.2.2.1 If the {content type} of the ·actual type
22360 * definition· is mixed, then the *initial value* of the
22361 * item must match the canonical lexical representation
22362 * of the {value constraint} value.
22363 *
22364 * ... the *initial value* of an element information
22365 * item is the string composed of, in order, the
22366 * [character code] of each character information item in
22367 * the [children] of that element information item.
22368 */
22369 if (! xmlStrEqual(inode->value, inode->decl->value)){
22370 /*
22371 * VAL TODO: Report invalid & expected values as well.
22372 * VAL TODO: Implement the canonical stuff.
22373 */
22374 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22375 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22376 ret, NULL, NULL,
22377 "The initial value '%s' does not match the fixed "
22378 "value constraint '%s'",
22379 inode->value, inode->decl->value);
22380 goto end_elem;
22381 }
22382 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22383 /*
22384 * 5.2.2.2.2 If the {content type} of the ·actual type
22385 * definition· is a simple type definition, then the
22386 * *actual value* of the item must match the canonical
22387 * lexical representation of the {value constraint} value.
22388 */
22389 /*
22390 * VAL TODO: *actual value* is the normalized value, impl.
22391 * this.
22392 * VAL TODO: Report invalid & expected values as well.
22393 * VAL TODO: Implement a comparison with the computed values.
22394 */
22395 if (! xmlStrEqual(inode->value,
22396 inode->decl->value)) {
22397 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22398 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22399 ret, NULL, NULL,
22400 "The actual value '%s' does not match the fixed "
22401 "value constraint '%s'",
22402 inode->value,
22403 inode->decl->value);
22404 goto end_elem;
22405 }
22406 }
22407 }
22408 }
22409 }
22410
22411end_elem:
22412 if (vctxt->depth < 0) {
22413 /* TODO: raise error? */
22414 return (0);
22415 }
22416 if (vctxt->depth == vctxt->skipDepth)
22417 vctxt->skipDepth = -1;
22418 /*
22419 * Evaluate the history of XPath state objects.
22420 */
22421 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22422 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022423 /*
22424 * TODO: 6 The element information item must be ·valid· with respect to each of
22425 * the {identity-constraint definitions} as per Identity-constraint
22426 * Satisfied (§3.11.4).
22427 */
22428 /*
22429 * Validate IDC keyrefs.
22430 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022431 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22432 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022433 /*
22434 * Merge/free the IDC table.
22435 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022436 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022437#ifdef DEBUG_IDC
22438 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022439 inode->nsName,
22440 inode->localName,
22441 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022442#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022443 if (vctxt->depth > 0) {
22444 /*
22445 * Merge the IDC node table with the table of the parent node.
22446 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022447 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22448 goto internal_error;
22449 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022450 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022451 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022452 * Clear the current ielem.
22453 * VAL TODO: Don't free the PSVI IDC tables if they are
22454 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022455 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022456 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022457 /*
22458 * Skip further processing if we are on the validation root.
22459 */
22460 if (vctxt->depth == 0) {
22461 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022462 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022463 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022464 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022465 /*
22466 * Reset the bubbleDepth if needed.
22467 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022468 if (vctxt->aidcs != NULL) {
22469 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22470 do {
22471 if (aidc->bubbleDepth == vctxt->depth) {
22472 /*
22473 * A bubbleDepth of a key/unique IDC matches the current
22474 * depth, this means that we are leaving the scope of the
22475 * top-most keyref IDC.
22476 */
22477 aidc->bubbleDepth = -1;
22478 }
22479 aidc = aidc->next;
22480 } while (aidc != NULL);
22481 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022482 vctxt->depth--;
22483 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022484 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022485 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022486 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22487 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022488 return (ret);
22489
22490internal_error:
22491 vctxt->err = -1;
22492 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022493}
22494
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022495/*
22496* 3.4.4 Complex Type Definition Validation Rules
22497* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22498*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022499static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022500xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022501{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022502 xmlSchemaNodeInfoPtr pielem;
22503 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022504 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022505
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022506 if (vctxt->depth <= 0) {
22507 VERROR_INT("xmlSchemaValidateChildElem",
22508 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022509 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022510 }
22511 pielem = vctxt->elemInfos[vctxt->depth -1];
22512 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22513 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022514 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022515 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022516 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022517 if (INODE_NILLED(pielem)) {
22518 /*
22519 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22520 */
22521 ACTIVATE_PARENT_ELEM;
22522 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22523 VERROR(ret, NULL,
22524 "Neither character nor element content is allowed, "
22525 "because the element was 'nilled'");
22526 ACTIVATE_ELEM;
22527 goto unexpected_elem;
22528 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022529
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022530 ptype = pielem->typeDef;
22531
22532 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22533 /*
22534 * Workaround for "anyType": we have currently no content model
22535 * assigned for "anyType", so handle it explicitely.
22536 * "anyType" has an unbounded, lax "any" wildcard.
22537 */
22538 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22539 vctxt->inode->localName,
22540 vctxt->inode->nsName);
22541
22542 if (vctxt->inode->decl == NULL) {
22543 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022544 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022545 * Process "xsi:type".
22546 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022547 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022548 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22549 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22550 if (iattr != NULL) {
22551 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22552 &(vctxt->inode->typeDef), NULL);
22553 if (ret != 0) {
22554 if (ret == -1) {
22555 VERROR_INT("xmlSchemaValidateChildElem",
22556 "calling xmlSchemaProcessXSIType() to "
22557 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022558 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022559 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022560 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022561 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022562 } else {
22563 /*
22564 * Fallback to "anyType".
22565 *
22566 * SPEC (cvc-assess-elt)
22567 * "If the item cannot be ·strictly assessed·, [...]
22568 * an element information item's schema validity may be laxly
22569 * assessed if its ·context-determined declaration· is not
22570 * skip by ·validating· with respect to the ·ur-type
22571 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22572 */
22573 vctxt->inode->typeDef =
22574 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022575 }
22576 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022577 return (0);
22578 }
22579
22580 switch (ptype->contentType) {
22581 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022582 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022583 * SPEC (2.1) "If the {content type} is empty, then the
22584 * element information item has no character or element
22585 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022586 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022587 ACTIVATE_PARENT_ELEM
22588 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22589 VERROR(ret, NULL,
22590 "Element content is not allowed, "
22591 "because the content type is empty");
22592 ACTIVATE_ELEM
22593 goto unexpected_elem;
22594 break;
22595
22596 case XML_SCHEMA_CONTENT_MIXED:
22597 case XML_SCHEMA_CONTENT_ELEMENTS: {
22598 xmlRegExecCtxtPtr regexCtxt;
22599 xmlChar *values[10];
22600 int terminal, nbval = 10, nbneg;
22601
22602 /* VAL TODO: Optimized "anyType" validation.*/
22603
22604 if (ptype->contModel == NULL) {
22605 VERROR_INT("xmlSchemaValidateChildElem",
22606 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022607 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022608 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022609 /*
22610 * Safety belf for evaluation if the cont. model was already
22611 * examined to be invalid.
22612 */
22613 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22614 VERROR_INT("xmlSchemaValidateChildElem",
22615 "validating elem, but elem content is already invalid");
22616 return (-1);
22617 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022618
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022619 regexCtxt = pielem->regexCtxt;
22620 if (regexCtxt == NULL) {
22621 /*
22622 * Create the regex context.
22623 */
22624 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22625 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22626 vctxt);
22627 if (regexCtxt == NULL) {
22628 VERROR_INT("xmlSchemaValidateChildElem",
22629 "failed to create a regex context");
22630 return (-1);
22631 }
22632 pielem->regexCtxt = regexCtxt;
22633#ifdef DEBUG_AUTOMATA
22634 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22635 pielem->localName);
22636#endif
22637 }
22638
22639 /*
22640 * SPEC (2.4) "If the {content type} is element-only or mixed,
22641 * then the sequence of the element information item's
22642 * element information item [children], if any, taken in
22643 * order, is ·valid· with respect to the {content type}'s
22644 * particle, as defined in Element Sequence Locally Valid
22645 * (Particle) (§3.9.4)."
22646 */
22647 ret = xmlRegExecPushString2(regexCtxt,
22648 vctxt->inode->localName,
22649 vctxt->inode->nsName,
22650 vctxt->inode);
22651#ifdef DEBUG_AUTOMATA
22652 if (ret < 0)
22653 xmlGenericError(xmlGenericErrorContext,
22654 "AUTOMATON push ERROR for '%s' on '%s'\n",
22655 vctxt->inode->localName, pielem->localName);
22656 else
22657 xmlGenericError(xmlGenericErrorContext,
22658 "AUTOMATON push OK for '%s' on '%s'\n",
22659 vctxt->inode->localName, pielem->localName);
22660#endif
22661 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22662 VERROR_INT("xmlSchemaValidateChildElem",
22663 "calling xmlRegExecPushString2()");
22664 return (-1);
22665 }
22666 if (ret < 0) {
22667 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22668 &values[0], &terminal);
22669 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22670 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22671 "This element is not expected",
22672 nbval, nbneg, values);
22673 ret = vctxt->err;
22674 goto unexpected_elem;
22675 } else
22676 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022677 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022678 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022679 case XML_SCHEMA_CONTENT_SIMPLE:
22680 case XML_SCHEMA_CONTENT_BASIC:
22681 ACTIVATE_PARENT_ELEM
22682 if (IS_COMPLEX_TYPE(ptype)) {
22683 /*
22684 * SPEC (cvc-complex-type) (2.2)
22685 * "If the {content type} is a simple type definition, then
22686 * the element information item has no element information
22687 * item [children], ..."
22688 */
22689 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22690 VERROR(ret, NULL, "Element content is not allowed, "
22691 "because the content type is a simple type definition");
22692 } else {
22693 /*
22694 * SPEC (cvc-type) (3.1.2) "The element information item must
22695 * have no element information item [children]."
22696 */
22697 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22698 VERROR(ret, NULL, "Element content is not allowed, "
22699 "because the type definition is simple");
22700 }
22701 ACTIVATE_ELEM
22702 ret = vctxt->err;
22703 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022704 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022705
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022706 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022707 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022708 }
22709 return (ret);
22710unexpected_elem:
22711 /*
22712 * Pop this element and set the skipDepth to skip
22713 * all further content of the parent element.
22714 */
22715 vctxt->skipDepth = vctxt->depth;
22716 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22717 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22718 return (ret);
22719}
22720
22721#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22722#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22723#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22724
22725static int
22726xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22727 int nodeType, const xmlChar *value, int len,
22728 int mode, int *consumed)
22729{
22730 /*
22731 * Unfortunately we have to duplicate the text sometimes.
22732 * OPTIMIZE: Maybe we could skip it, if:
22733 * 1. content type is simple
22734 * 2. whitespace is "collapse"
22735 * 3. it consists of whitespace only
22736 *
22737 * Process character content.
22738 */
22739 if (consumed != NULL)
22740 *consumed = 0;
22741 if (INODE_NILLED(vctxt->inode)) {
22742 /*
22743 * SPEC cvc-elt (3.3.4 - 3.2.1)
22744 * "The element information item must have no character or
22745 * element information item [children]."
22746 */
22747 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22748 "Neither character nor element content is allowed "
22749 "because the element is 'nilled'");
22750 return (vctxt->err);
22751 }
22752 /*
22753 * SPEC (2.1) "If the {content type} is empty, then the
22754 * element information item has no character or element
22755 * information item [children]."
22756 */
22757 if (vctxt->inode->typeDef->contentType ==
22758 XML_SCHEMA_CONTENT_EMPTY) {
22759 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22760 "Character content is not allowed, "
22761 "because the content type is empty");
22762 return (vctxt->err);
22763 }
22764
22765 if (vctxt->inode->typeDef->contentType ==
22766 XML_SCHEMA_CONTENT_ELEMENTS) {
22767 if ((nodeType != XML_TEXT_NODE) ||
22768 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22769 /*
22770 * SPEC cvc-complex-type (2.3)
22771 * "If the {content type} is element-only, then the
22772 * element information item has no character information
22773 * item [children] other than those whose [character
22774 * code] is defined as a white space in [XML 1.0 (Second
22775 * Edition)]."
22776 */
22777 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22778 "Character content other than whitespace is not allowed "
22779 "because the content type is 'element-only'");
22780 return (vctxt->err);
22781 }
22782 return (0);
22783 }
22784
22785 if ((value == NULL) || (value[0] == 0))
22786 return (0);
22787 /*
22788 * Save the value.
22789 * NOTE that even if the content type is *mixed*, we need the
22790 * *initial value* for default/fixed value constraints.
22791 */
22792 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22793 ((vctxt->inode->decl == NULL) ||
22794 (vctxt->inode->decl->value == NULL)))
22795 return (0);
22796
22797 if (vctxt->inode->value == NULL) {
22798 /*
22799 * Set the value.
22800 */
22801 switch (mode) {
22802 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22803 /*
22804 * When working on a tree.
22805 */
22806 vctxt->inode->value = value;
22807 break;
22808 case XML_SCHEMA_PUSH_TEXT_CREATED:
22809 /*
22810 * When working with the reader.
22811 * The value will be freed by the element info.
22812 */
22813 vctxt->inode->value = value;
22814 if (consumed != NULL)
22815 *consumed = 1;
22816 vctxt->inode->flags |=
22817 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22818 break;
22819 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22820 /*
22821 * When working with SAX.
22822 * The value will be freed by the element info.
22823 */
22824 if (len != -1)
22825 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22826 else
22827 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22828 vctxt->inode->flags |=
22829 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22830 break;
22831 default:
22832 break;
22833 }
22834 } else {
22835 /*
22836 * Concat the value.
22837 */
22838 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022839 vctxt->inode->value = BAD_CAST xmlStrncat(
22840 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022841 } else {
22842 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022843 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022844 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22845 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022846 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022847
22848 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022849}
22850
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022851static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022852xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022853{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022854 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022855
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022856 if ((vctxt->skipDepth != -1) &&
22857 (vctxt->depth >= vctxt->skipDepth)) {
22858 VERROR_INT("xmlSchemaValidateElem",
22859 "in skip-state");
22860 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022861 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022862 if (vctxt->xsiAssemble) {
22863 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22864 goto internal_error;
22865 }
22866 if (vctxt->depth > 0) {
22867 /*
22868 * Validate this element against the content model
22869 * of the parent.
22870 */
22871 ret = xmlSchemaValidateChildElem(vctxt);
22872 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022873 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022874 VERROR_INT("xmlSchemaValidateElem",
22875 "calling xmlSchemaStreamValidateChildElement()");
22876 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022877 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022878 goto exit;
22879 }
22880 if (vctxt->depth == vctxt->skipDepth)
22881 goto exit;
22882 if ((vctxt->inode->decl == NULL) &&
22883 (vctxt->inode->typeDef == NULL)) {
22884 VERROR_INT("xmlSchemaValidateElem",
22885 "the child element was valid but neither the "
22886 "declaration nor the type was set");
22887 goto internal_error;
22888 }
22889 } else {
22890 /*
22891 * Get the declaration of the validation root.
22892 */
22893 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22894 vctxt->inode->localName,
22895 vctxt->inode->nsName);
22896 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022897 ret = XML_SCHEMAV_CVC_ELT_1;
22898 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022899 "No matching global declaration available "
22900 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022901 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022902 }
22903 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022904
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022905 if (vctxt->inode->decl == NULL)
22906 goto type_validation;
22907
22908 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22909 int skip;
22910 /*
22911 * Wildcards.
22912 */
22913 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22914 if (ret != 0) {
22915 if (ret < 0) {
22916 VERROR_INT("xmlSchemaValidateElem",
22917 "calling xmlSchemaValidateElemWildcard()");
22918 goto internal_error;
22919 }
22920 goto exit;
22921 }
22922 if (skip) {
22923 vctxt->skipDepth = vctxt->depth;
22924 goto exit;
22925 }
22926 /*
22927 * The declaration might be set by the wildcard validation,
22928 * when the processContents is "lax" or "strict".
22929 */
22930 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22931 /*
22932 * Clear the "decl" field to not confuse further processing.
22933 */
22934 vctxt->inode->decl = NULL;
22935 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022936 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022937 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022938 /*
22939 * Validate against the declaration.
22940 */
22941 ret = xmlSchemaValidateElemDecl(vctxt);
22942 if (ret != 0) {
22943 if (ret < 0) {
22944 VERROR_INT("xmlSchemaValidateElem",
22945 "calling xmlSchemaValidateElemDecl()");
22946 goto internal_error;
22947 }
22948 goto exit;
22949 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022950 /*
22951 * Validate against the type definition.
22952 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022953type_validation:
22954
22955 if (vctxt->inode->typeDef == NULL) {
22956 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22957 ret = XML_SCHEMAV_CVC_TYPE_1;
22958 VERROR(ret, NULL,
22959 "The type definition is absent");
22960 goto exit;
22961 }
22962 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22963 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22964 ret = XML_SCHEMAV_CVC_TYPE_2;
22965 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022966 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022967 goto exit;
22968 }
22969 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022970 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022971 * during validation against the declaration. This must be done
22972 * _before_ attribute validation.
22973 */
22974 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22975 if (ret == -1) {
22976 VERROR_INT("xmlSchemaValidateElem",
22977 "calling xmlSchemaXPathEvaluate()");
22978 goto internal_error;
22979 }
22980 /*
22981 * Validate attributes.
22982 */
22983 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22984 if ((vctxt->nbAttrInfos != 0) ||
22985 (vctxt->inode->typeDef->attributeUses != NULL)) {
22986
22987 ret = xmlSchemaVAttributesComplex(vctxt);
22988 }
22989 } else if (vctxt->nbAttrInfos != 0) {
22990
22991 ret = xmlSchemaVAttributesSimple(vctxt);
22992 }
22993 /*
22994 * Clear registered attributes.
22995 */
22996 if (vctxt->nbAttrInfos != 0)
22997 xmlSchemaClearAttrInfos(vctxt);
22998 if (ret == -1) {
22999 VERROR_INT("xmlSchemaValidateElem",
23000 "calling attributes validation");
23001 goto internal_error;
23002 }
23003 /*
23004 * Don't return an error if attributes are invalid on purpose.
23005 */
23006 ret = 0;
23007
23008exit:
23009 if (ret != 0)
23010 vctxt->skipDepth = vctxt->depth;
23011 return (ret);
23012internal_error:
23013 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023014}
23015
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023016#ifdef XML_SCHEMA_READER_ENABLED
23017static int
23018xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023019{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023020 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
23021 int depth, nodeType, ret = 0, consumed;
23022 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023023
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023024 vctxt->depth = -1;
23025 ret = xmlTextReaderRead(vctxt->reader);
23026 /*
23027 * Move to the document element.
23028 */
23029 while (ret == 1) {
23030 nodeType = xmlTextReaderNodeType(vctxt->reader);
23031 if (nodeType == XML_ELEMENT_NODE)
23032 goto root_found;
23033 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023034 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023035 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023036
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023037root_found:
23038
23039 do {
23040 depth = xmlTextReaderDepth(vctxt->reader);
23041 nodeType = xmlTextReaderNodeType(vctxt->reader);
23042
23043 if (nodeType == XML_ELEMENT_NODE) {
23044
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023045 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023046 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23047 VERROR_INT("xmlSchemaVReaderWalk",
23048 "calling xmlSchemaValidatorPushElem()");
23049 goto internal_error;
23050 }
23051 ielem = vctxt->inode;
23052 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23053 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23054 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23055 /*
23056 * Is the element empty?
23057 */
23058 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23059 if (ret == -1) {
23060 VERROR_INT("xmlSchemaVReaderWalk",
23061 "calling xmlTextReaderIsEmptyElement()");
23062 goto internal_error;
23063 }
23064 if (ret) {
23065 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23066 }
23067 /*
23068 * Register attributes.
23069 */
23070 vctxt->nbAttrInfos = 0;
23071 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23072 if (ret == -1) {
23073 VERROR_INT("xmlSchemaVReaderWalk",
23074 "calling xmlTextReaderMoveToFirstAttribute()");
23075 goto internal_error;
23076 }
23077 if (ret == 1) {
23078 do {
23079 /*
23080 * VAL TODO: How do we know that the reader works on a
23081 * node tree, to be able to pass a node here?
23082 */
23083 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23084 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23085 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23086 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23087
23088 VERROR_INT("xmlSchemaVReaderWalk",
23089 "calling xmlSchemaValidatorPushAttribute()");
23090 goto internal_error;
23091 }
23092 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23093 if (ret == -1) {
23094 VERROR_INT("xmlSchemaVReaderWalk",
23095 "calling xmlTextReaderMoveToFirstAttribute()");
23096 goto internal_error;
23097 }
23098 } while (ret == 1);
23099 /*
23100 * Back to element position.
23101 */
23102 ret = xmlTextReaderMoveToElement(vctxt->reader);
23103 if (ret == -1) {
23104 VERROR_INT("xmlSchemaVReaderWalk",
23105 "calling xmlTextReaderMoveToElement()");
23106 goto internal_error;
23107 }
23108 }
23109 /*
23110 * Validate the element.
23111 */
23112 ret= xmlSchemaValidateElem(vctxt);
23113 if (ret != 0) {
23114 if (ret == -1) {
23115 VERROR_INT("xmlSchemaVReaderWalk",
23116 "calling xmlSchemaValidateElem()");
23117 goto internal_error;
23118 }
23119 goto exit;
23120 }
23121 if (vctxt->depth == vctxt->skipDepth) {
23122 int curDepth;
23123 /*
23124 * Skip all content.
23125 */
23126 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23127 ret = xmlTextReaderRead(vctxt->reader);
23128 curDepth = xmlTextReaderDepth(vctxt->reader);
23129 while ((ret == 1) && (curDepth != depth)) {
23130 ret = xmlTextReaderRead(vctxt->reader);
23131 curDepth = xmlTextReaderDepth(vctxt->reader);
23132 }
23133 if (ret < 0) {
23134 /*
23135 * VAL TODO: A reader error occured; what to do here?
23136 */
23137 ret = 1;
23138 goto exit;
23139 }
23140 }
23141 goto leave_elem;
23142 }
23143 /*
23144 * READER VAL TODO: Is an END_ELEM really never called
23145 * if the elem is empty?
23146 */
23147 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23148 goto leave_elem;
23149 } else if (nodeType == END_ELEM) {
23150 /*
23151 * Process END of element.
23152 */
23153leave_elem:
23154 ret = xmlSchemaValidatorPopElem(vctxt);
23155 if (ret != 0) {
23156 if (ret < 0) {
23157 VERROR_INT("xmlSchemaVReaderWalk",
23158 "calling xmlSchemaValidatorPopElem()");
23159 goto internal_error;
23160 }
23161 goto exit;
23162 }
23163 if (vctxt->depth >= 0)
23164 ielem = vctxt->inode;
23165 else
23166 ielem = NULL;
23167 } else if ((nodeType == XML_TEXT_NODE) ||
23168 (nodeType == XML_CDATA_SECTION_NODE) ||
23169 (nodeType == WHTSP) ||
23170 (nodeType == SIGN_WHTSP)) {
23171 /*
23172 * Process character content.
23173 */
23174 xmlChar *value;
23175
23176 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23177 nodeType = XML_TEXT_NODE;
23178
23179 value = xmlTextReaderValue(vctxt->reader);
23180 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23181 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23182 if (! consumed)
23183 xmlFree(value);
23184 if (ret == -1) {
23185 VERROR_INT("xmlSchemaVReaderWalk",
23186 "calling xmlSchemaVPushText()");
23187 goto internal_error;
23188 }
23189 } else if ((nodeType == XML_ENTITY_NODE) ||
23190 (nodeType == XML_ENTITY_REF_NODE)) {
23191 /*
23192 * VAL TODO: What to do with entities?
23193 */
23194 TODO
23195 }
23196 /*
23197 * Read next node.
23198 */
23199 ret = xmlTextReaderRead(vctxt->reader);
23200 } while (ret == 1);
23201
23202exit:
23203 return (ret);
23204internal_error:
23205 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023206}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023207#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023208
23209/************************************************************************
23210 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023211 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023212 * *
23213 ************************************************************************/
23214
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023215#ifdef XML_SCHEMA_SAX_ENABLED
23216/*
23217* Process text content.
23218*/
23219static void
23220xmlSchemaSAXHandleText(void *ctx,
23221 const xmlChar * ch,
23222 int len)
23223{
23224 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23225
23226 if (vctxt->depth < 0)
23227 return;
23228 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23229 return;
23230 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23231 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23232 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23233 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23234 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23235 "calling xmlSchemaVPushText()");
23236 vctxt->err = -1;
23237 xmlStopParser(vctxt->parserCtxt);
23238 }
23239}
23240
23241/*
23242* Process CDATA content.
23243*/
23244static void
23245xmlSchemaSAXHandleCDataSection(void *ctx,
23246 const xmlChar * ch,
23247 int len)
23248{
23249 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23250
23251 if (vctxt->depth < 0)
23252 return;
23253 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23254 return;
23255 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23256 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23257 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23258 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23259 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23260 "calling xmlSchemaVPushText()");
23261 vctxt->err = -1;
23262 xmlStopParser(vctxt->parserCtxt);
23263 }
23264}
23265
23266static void
23267xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23268 const xmlChar * name ATTRIBUTE_UNUSED)
23269{
23270 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23271
23272 if (vctxt->depth < 0)
23273 return;
23274 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23275 return;
23276 /* SAX VAL TODO: What to do here? */
23277 TODO
23278}
23279
23280static void
23281xmlSchemaSAXHandleStartElementNs(void *ctx,
23282 const xmlChar * localname,
23283 const xmlChar * prefix ATTRIBUTE_UNUSED,
23284 const xmlChar * URI,
23285 int nb_namespaces,
23286 const xmlChar ** namespaces,
23287 int nb_attributes,
23288 int nb_defaulted ATTRIBUTE_UNUSED,
23289 const xmlChar ** attributes)
23290{
23291 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23292 int ret;
23293 xmlSchemaNodeInfoPtr ielem;
23294 int i, j;
23295
23296 /*
23297 * SAX VAL TODO: What to do with nb_defaulted?
23298 */
23299 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023300 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023301 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023302 vctxt->depth++;
23303 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023304 return;
23305 /*
23306 * Push the element.
23307 */
23308 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23309 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23310 "calling xmlSchemaValidatorPushElem()");
23311 goto internal_error;
23312 }
23313 ielem = vctxt->inode;
23314 ielem->localName = localname;
23315 ielem->nsName = URI;
23316 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23317 /*
23318 * Register namespaces on the elem info.
23319 */
23320 if (nb_namespaces != 0) {
23321 /*
23322 * Although the parser builds its own namespace list,
23323 * we have no access to it, so we'll use an own one.
23324 */
23325 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23326 /*
23327 * Store prefix and namespace name.
23328 */
23329 if (ielem->nsBindings == NULL) {
23330 ielem->nsBindings =
23331 (const xmlChar **) xmlMalloc(10 *
23332 sizeof(const xmlChar *));
23333 if (ielem->nsBindings == NULL) {
23334 xmlSchemaVErrMemory(vctxt,
23335 "allocating namespace bindings for SAX validation",
23336 NULL);
23337 goto internal_error;
23338 }
23339 ielem->nbNsBindings = 0;
23340 ielem->sizeNsBindings = 5;
23341 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23342 ielem->sizeNsBindings *= 2;
23343 ielem->nsBindings =
23344 (const xmlChar **) xmlRealloc(
23345 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023346 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023347 if (ielem->nsBindings == NULL) {
23348 xmlSchemaVErrMemory(vctxt,
23349 "re-allocating namespace bindings for SAX validation",
23350 NULL);
23351 goto internal_error;
23352 }
23353 }
23354
23355 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23356 if (namespaces[j+1][0] == 0) {
23357 /*
23358 * Handle xmlns="".
23359 */
23360 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23361 } else
23362 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23363 namespaces[j+1];
23364 ielem->nbNsBindings++;
23365 }
23366 }
23367 /*
23368 * Register attributes.
23369 * SAX VAL TODO: We are not adding namespace declaration
23370 * attributes yet.
23371 */
23372 if (nb_attributes != 0) {
23373 xmlChar *value;
23374
23375 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23376 /*
23377 * Duplicate the value.
23378 */
23379 value = xmlStrndup(attributes[j+3],
23380 attributes[j+4] - attributes[j+3]);
23381 ret = xmlSchemaValidatorPushAttribute(vctxt,
23382 NULL, attributes[j], attributes[j+2], 0,
23383 value, 1);
23384 if (ret == -1) {
23385 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23386 "calling xmlSchemaValidatorPushAttribute()");
23387 goto internal_error;
23388 }
23389 }
23390 }
23391 /*
23392 * Validate the element.
23393 */
23394 ret = xmlSchemaValidateElem(vctxt);
23395 if (ret != 0) {
23396 if (ret == -1) {
23397 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23398 "calling xmlSchemaValidateElem()");
23399 goto internal_error;
23400 }
23401 goto exit;
23402 }
23403
23404exit:
23405 return;
23406internal_error:
23407 vctxt->err = -1;
23408 xmlStopParser(vctxt->parserCtxt);
23409 return;
23410}
23411
23412static void
23413xmlSchemaSAXHandleEndElementNs(void *ctx,
23414 const xmlChar * localname ATTRIBUTE_UNUSED,
23415 const xmlChar * prefix ATTRIBUTE_UNUSED,
23416 const xmlChar * URI ATTRIBUTE_UNUSED)
23417{
23418 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23419 int res;
23420
23421 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023422 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023423 */
23424 if (vctxt->skipDepth != -1) {
23425 if (vctxt->depth > vctxt->skipDepth) {
23426 vctxt->depth--;
23427 return;
23428 } else
23429 vctxt->skipDepth = -1;
23430 }
23431 /*
23432 * SAX VAL TODO: Just a temporary check.
23433 */
23434 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23435 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23436 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23437 "elem pop mismatch");
23438 }
23439 res = xmlSchemaValidatorPopElem(vctxt);
23440 if (res != 0) {
23441 if (res < 0) {
23442 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23443 "calling xmlSchemaValidatorPopElem()");
23444 goto internal_error;
23445 }
23446 goto exit;
23447 }
23448exit:
23449 return;
23450internal_error:
23451 vctxt->err = -1;
23452 xmlStopParser(vctxt->parserCtxt);
23453 return;
23454}
23455#endif
23456
Daniel Veillard4255d502002-04-16 15:50:10 +000023457/************************************************************************
23458 * *
23459 * Validation interfaces *
23460 * *
23461 ************************************************************************/
23462
23463/**
23464 * xmlSchemaNewValidCtxt:
23465 * @schema: a precompiled XML Schemas
23466 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023467 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023468 *
23469 * Returns the validation context or NULL in case of error
23470 */
23471xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023472xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23473{
Daniel Veillard4255d502002-04-16 15:50:10 +000023474 xmlSchemaValidCtxtPtr ret;
23475
23476 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23477 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023478 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023479 return (NULL);
23480 }
23481 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023482 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23483 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023484 return (ret);
23485}
23486
23487/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023488 * xmlSchemaClearValidCtxt:
23489 * @ctxt: the schema validation context
23490 *
23491 * Free the resources associated to the schema validation context;
23492 * leaves some fields alive intended for reuse of the context.
23493 */
23494static void
23495xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23496{
23497 if (vctxt == NULL)
23498 return;
23499
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023500 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023501 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023502 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023503#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023504 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023505#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023506 if (vctxt->value != NULL) {
23507 xmlSchemaFreeValue(vctxt->value);
23508 vctxt->value = NULL;
23509 }
23510 /*
23511 * Augmented IDC information.
23512 */
23513 if (vctxt->aidcs != NULL) {
23514 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23515 do {
23516 next = cur->next;
23517 xmlFree(cur);
23518 cur = next;
23519 } while (cur != NULL);
23520 vctxt->aidcs = NULL;
23521 }
23522 if (vctxt->idcNodes != NULL) {
23523 int i;
23524 xmlSchemaPSVIIDCNodePtr item;
23525
23526 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023527 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023528 xmlFree(item->keys);
23529 xmlFree(item);
23530 }
23531 xmlFree(vctxt->idcNodes);
23532 vctxt->idcNodes = NULL;
23533 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023534 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023535 * Note that we won't delete the XPath state pool here.
23536 */
23537 if (vctxt->xpathStates != NULL) {
23538 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23539 vctxt->xpathStates = NULL;
23540 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023541 /*
23542 * Attribute info.
23543 */
23544 if (vctxt->nbAttrInfos != 0) {
23545 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023546 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023547 /*
23548 * Element info.
23549 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023550 if (vctxt->elemInfos != NULL) {
23551 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023552 xmlSchemaNodeInfoPtr ei;
23553
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023554 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023555 ei = vctxt->elemInfos[i];
23556 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023557 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023558 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023559 }
23560 }
23561}
23562
23563/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023564 * xmlSchemaFreeValidCtxt:
23565 * @ctxt: the schema validation context
23566 *
23567 * Free the resources associated to the schema validation context
23568 */
23569void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023570xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23571{
Daniel Veillard4255d502002-04-16 15:50:10 +000023572 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023573 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023574 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023575 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023576 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023577 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023578 if (ctxt->idcNodes != NULL) {
23579 int i;
23580 xmlSchemaPSVIIDCNodePtr item;
23581
23582 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023583 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023584 xmlFree(item->keys);
23585 xmlFree(item);
23586 }
23587 xmlFree(ctxt->idcNodes);
23588 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023589 if (ctxt->idcKeys != NULL) {
23590 int i;
23591 for (i = 0; i < ctxt->nbIdcKeys; i++)
23592 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23593 xmlFree(ctxt->idcKeys);
23594 }
23595
23596 if (ctxt->xpathStates != NULL)
23597 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23598 if (ctxt->xpathStatePool != NULL)
23599 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23600
23601 /*
23602 * Augmented IDC information.
23603 */
23604 if (ctxt->aidcs != NULL) {
23605 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23606 do {
23607 next = cur->next;
23608 xmlFree(cur);
23609 cur = next;
23610 } while (cur != NULL);
23611 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023612 if (ctxt->attrInfos != NULL) {
23613 int i;
23614 xmlSchemaAttrInfoPtr attr;
23615
23616 /* Just a paranoid call to the cleanup. */
23617 if (ctxt->nbAttrInfos != 0)
23618 xmlSchemaClearAttrInfos(ctxt);
23619 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23620 attr = ctxt->attrInfos[i];
23621 xmlFree(attr);
23622 }
23623 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023624 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023625 if (ctxt->elemInfos != NULL) {
23626 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023627 xmlSchemaNodeInfoPtr ei;
23628
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023629 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023630 ei = ctxt->elemInfos[i];
23631 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023632 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023633 xmlSchemaClearElemInfo(ei);
23634 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023635 }
23636 xmlFree(ctxt->elemInfos);
23637 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023638 if (ctxt->dict != NULL)
23639 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023640 xmlFree(ctxt);
23641}
23642
23643/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000023644 * xmlSchemaIsValid:
23645 * @ctxt: the schema validation context
23646 *
23647 * Check if any error was detected during validation.
23648 *
23649 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
23650 * of internal error.
23651 */
23652int
23653xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
23654{
23655 if (ctxt == NULL)
23656 return(-1);
23657 return(ctxt->err == 0);
23658}
23659
23660/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023661 * xmlSchemaSetValidErrors:
23662 * @ctxt: a schema validation context
23663 * @err: the error function
23664 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023665 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023666 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023667 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023668 */
23669void
23670xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023671 xmlSchemaValidityErrorFunc err,
23672 xmlSchemaValidityWarningFunc warn, void *ctx)
23673{
Daniel Veillard4255d502002-04-16 15:50:10 +000023674 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023675 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023676 ctxt->error = err;
23677 ctxt->warning = warn;
23678 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023679 if (ctxt->pctxt != NULL)
23680 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023681}
23682
23683/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000023684 * xmlSchemaSetValidStructuredErrors:
23685 * @ctxt: a schema validation context
23686 * @serror: the structured error function
23687 * @ctx: the functions context
23688 *
23689 * Set the structured error callback
23690 */
23691void
23692xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
23693 xmlStructuredErrorFunc serror, void *ctx)
23694{
23695 if (ctxt == NULL)
23696 return;
23697 ctxt->serror = serror;
23698 ctxt->error = NULL;
23699 ctxt->warning = NULL;
23700 ctxt->userData = ctx;
23701}
23702
23703/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023704 * xmlSchemaGetValidErrors:
23705 * @ctxt: a XML-Schema validation context
23706 * @err: the error function result
23707 * @warn: the warning function result
23708 * @ctx: the functions context result
23709 *
23710 * Get the error and warning callback informations
23711 *
23712 * Returns -1 in case of error and 0 otherwise
23713 */
23714int
23715xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23716 xmlSchemaValidityErrorFunc * err,
23717 xmlSchemaValidityWarningFunc * warn, void **ctx)
23718{
23719 if (ctxt == NULL)
23720 return (-1);
23721 if (err != NULL)
23722 *err = ctxt->error;
23723 if (warn != NULL)
23724 *warn = ctxt->warning;
23725 if (ctx != NULL)
23726 *ctx = ctxt->userData;
23727 return (0);
23728}
23729
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023730
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023731/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023732 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023733 * @ctxt: a schema validation context
23734 * @options: a combination of xmlSchemaValidOption
23735 *
23736 * Sets the options to be used during the validation.
23737 *
23738 * Returns 0 in case of success, -1 in case of an
23739 * API error.
23740 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023741int
23742xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23743 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023744
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023745{
23746 int i;
23747
23748 if (ctxt == NULL)
23749 return (-1);
23750 /*
23751 * WARNING: Change the start value if adding to the
23752 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023753 * TODO: Is there an other, more easy to maintain,
23754 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023755 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023756 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023757 if (options & 1<<i)
23758 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023759 }
23760 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023761 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023762}
23763
23764/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023765 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023766 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023767 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023768 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023769 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023770 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023771 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023772int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023773xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023774
23775{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023776 if (ctxt == NULL)
23777 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023778 else
23779 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023780}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023781
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023782static int
23783xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23784{
23785 xmlAttrPtr attr;
23786 int ret = 0;
23787 xmlSchemaNodeInfoPtr ielem = NULL;
23788 xmlNodePtr node, valRoot;
23789 const xmlChar *nsName;
23790
23791 /* DOC VAL TODO: Move this to the start function. */
23792 valRoot = xmlDocGetRootElement(vctxt->doc);
23793 if (valRoot == NULL) {
23794 /* VAL TODO: Error code? */
23795 VERROR(1, NULL, "The document has no document element");
23796 return (1);
23797 }
23798 vctxt->depth = -1;
23799 vctxt->validationRoot = valRoot;
23800 node = valRoot;
23801 while (node != NULL) {
23802 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23803 goto next_sibling;
23804 if (node->type == XML_ELEMENT_NODE) {
23805
23806 /*
23807 * Init the node-info.
23808 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023809 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023810 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23811 goto internal_error;
23812 ielem = vctxt->inode;
23813 ielem->node = node;
23814 ielem->localName = node->name;
23815 if (node->ns != NULL)
23816 ielem->nsName = node->ns->href;
23817 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23818 /*
23819 * Register attributes.
23820 * DOC VAL TODO: We do not register namespace declaration
23821 * attributes yet.
23822 */
23823 vctxt->nbAttrInfos = 0;
23824 if (node->properties != NULL) {
23825 attr = node->properties;
23826 do {
23827 if (attr->ns != NULL)
23828 nsName = attr->ns->href;
23829 else
23830 nsName = NULL;
23831 ret = xmlSchemaValidatorPushAttribute(vctxt,
23832 (xmlNodePtr) attr,
23833 attr->name, nsName, 0,
23834 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23835 if (ret == -1) {
23836 VERROR_INT("xmlSchemaDocWalk",
23837 "calling xmlSchemaValidatorPushAttribute()");
23838 goto internal_error;
23839 }
23840 attr = attr->next;
23841 } while (attr);
23842 }
23843 /*
23844 * Validate the element.
23845 */
23846 ret = xmlSchemaValidateElem(vctxt);
23847 if (ret != 0) {
23848 if (ret == -1) {
23849 VERROR_INT("xmlSchemaDocWalk",
23850 "calling xmlSchemaValidateElem()");
23851 goto internal_error;
23852 }
23853 /*
23854 * Don't stop validation; just skip the content
23855 * of this element.
23856 */
23857 goto leave_node;
23858 }
23859 if ((vctxt->skipDepth != -1) &&
23860 (vctxt->depth >= vctxt->skipDepth))
23861 goto leave_node;
23862 } else if ((node->type == XML_TEXT_NODE) ||
23863 (node->type == XML_CDATA_SECTION_NODE)) {
23864 /*
23865 * Process character content.
23866 */
23867 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23868 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23869 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23870 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23871 if (ret < 0) {
23872 VERROR_INT("xmlSchemaVDocWalk",
23873 "calling xmlSchemaVPushText()");
23874 goto internal_error;
23875 }
23876 /*
23877 * DOC VAL TODO: Should we skip further validation of the
23878 * element content here?
23879 */
23880 } else if ((node->type == XML_ENTITY_NODE) ||
23881 (node->type == XML_ENTITY_REF_NODE)) {
23882 /*
23883 * DOC VAL TODO: What to do with entities?
23884 */
23885 TODO
23886 } else {
23887 goto leave_node;
23888 /*
23889 * DOC VAL TODO: XInclude nodes, etc.
23890 */
23891 }
23892 /*
23893 * Walk the doc.
23894 */
23895 if (node->children != NULL) {
23896 node = node->children;
23897 continue;
23898 }
23899leave_node:
23900 if (node->type == XML_ELEMENT_NODE) {
23901 /*
23902 * Leaving the scope of an element.
23903 */
23904 if (node != vctxt->inode->node) {
23905 VERROR_INT("xmlSchemaVDocWalk",
23906 "element position mismatch");
23907 goto internal_error;
23908 }
23909 ret = xmlSchemaValidatorPopElem(vctxt);
23910 if (ret != 0) {
23911 if (ret < 0) {
23912 VERROR_INT("xmlSchemaVDocWalk",
23913 "calling xmlSchemaValidatorPopElem()");
23914 goto internal_error;
23915 }
23916 }
23917 if (node == valRoot)
23918 goto exit;
23919 }
23920next_sibling:
23921 if (node->next != NULL)
23922 node = node->next;
23923 else {
23924 node = node->parent;
23925 goto leave_node;
23926 }
23927 }
23928
23929exit:
23930 return (ret);
23931internal_error:
23932 return (-1);
23933}
23934
23935static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000023936xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023937 /*
23938 * Some initialization.
23939 */
23940 vctxt->err = 0;
23941 vctxt->nberrors = 0;
23942 vctxt->depth = -1;
23943 vctxt->skipDepth = -1;
23944 /*
23945 * Create a schema + parser if necessary.
23946 */
23947 if (vctxt->schema == NULL) {
23948
23949 if ((vctxt->pctxt == NULL) &&
23950 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23951 return (-1);
23952
23953 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23954 if (vctxt->schema == NULL) {
23955 VERROR_INT("xmlSchemaVStartValidation",
23956 "creating a schema");
23957 return (-1);
23958 }
23959 vctxt->xsiAssemble = 1;
23960 } else
23961 vctxt->xsiAssemble = 0;
23962 /*
23963 * Augment the IDC definitions.
23964 */
23965 if (vctxt->schema->idcDef != NULL) {
23966 xmlHashScan(vctxt->schema->idcDef,
23967 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23968 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000023969 return(0);
23970}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023971
Daniel Veillardf10ae122005-07-10 19:03:16 +000023972static void
23973xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023974 if (vctxt->xsiAssemble) {
23975 if (vctxt->schema != NULL) {
23976 xmlSchemaFree(vctxt->schema);
23977 vctxt->schema = NULL;
23978 }
23979 }
23980 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000023981}
23982
23983static int
23984xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23985{
23986 int ret = 0;
23987
23988 if (xmlSchemaPreRun(vctxt) < 0)
23989 return(-1);
23990
23991 if (vctxt->doc != NULL) {
23992 /*
23993 * Tree validation.
23994 */
23995 ret = xmlSchemaVDocWalk(vctxt);
23996#ifdef LIBXML_READER_ENABLED
23997 } else if (vctxt->reader != NULL) {
23998 /*
23999 * XML Reader validation.
24000 */
24001#ifdef XML_SCHEMA_READER_ENABLED
24002 ret = xmlSchemaVReaderWalk(vctxt);
24003#endif
24004#endif
24005 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
24006 /*
24007 * SAX validation.
24008 */
24009 ret = xmlParseDocument(vctxt->parserCtxt);
24010 } else {
24011 VERROR_INT("xmlSchemaVStartValidation",
24012 "no instance to validate");
24013 ret = -1;
24014 }
24015
24016 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024017 if (ret == 0)
24018 ret = vctxt->err;
24019 return (ret);
24020}
24021
24022/**
24023 * xmlSchemaValidateOneElement:
24024 * @ctxt: a schema validation context
24025 * @elem: an element node
24026 *
24027 * Validate a branch of a tree, starting with the given @elem.
24028 *
24029 * Returns 0 if the element and its subtree is valid, a positive error
24030 * code number otherwise and -1 in case of an internal or API error.
24031 */
24032int
24033xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24034{
24035 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24036 return (-1);
24037
24038 if (ctxt->schema == NULL)
24039 return (-1);
24040
24041 ctxt->doc = elem->doc;
24042 ctxt->node = elem;
24043 ctxt->validationRoot = elem;
24044 return(xmlSchemaVStart(ctxt));
24045}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024046
Daniel Veillard259f0df2004-08-18 09:13:18 +000024047/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024048 * xmlSchemaValidateDoc:
24049 * @ctxt: a schema validation context
24050 * @doc: a parsed document tree
24051 *
24052 * Validate a document tree in memory.
24053 *
24054 * Returns 0 if the document is schemas valid, a positive error code
24055 * number otherwise and -1 in case of internal or API error.
24056 */
24057int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024058xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24059{
Daniel Veillard4255d502002-04-16 15:50:10 +000024060 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024061 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024062
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024063 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024064 ctxt->node = xmlDocGetRootElement(doc);
24065 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024066 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024067 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24068 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024069 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024070 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024071 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024072 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024073 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024074}
24075
Daniel Veillardcdc82732005-07-08 15:04:06 +000024076
24077/************************************************************************
24078 * *
24079 * Function and data for SAX streaming API *
24080 * *
24081 ************************************************************************/
24082typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24083typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24084
24085struct _xmlSchemaSplitSAXData {
24086 xmlSAXHandlerPtr user_sax;
24087 void *user_data;
24088 xmlSchemaValidCtxtPtr ctxt;
24089 xmlSAXHandlerPtr schemas_sax;
24090};
24091
Daniel Veillard971771e2005-07-09 17:32:57 +000024092#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24093
24094struct _xmlSchemaSAXPlug {
24095 unsigned int magic;
24096
24097 /* the original callbacks informations */
24098 xmlSAXHandlerPtr *user_sax_ptr;
24099 xmlSAXHandlerPtr user_sax;
24100 void **user_data_ptr;
24101 void *user_data;
24102
24103 /* the block plugged back and validation informations */
24104 xmlSAXHandler schemas_sax;
24105 xmlSchemaValidCtxtPtr ctxt;
24106};
24107
Daniel Veillardcdc82732005-07-08 15:04:06 +000024108/* All those functions just bounces to the user provided SAX handlers */
24109static void
24110internalSubsetSplit(void *ctx, const xmlChar *name,
24111 const xmlChar *ExternalID, const xmlChar *SystemID)
24112{
Daniel Veillard971771e2005-07-09 17:32:57 +000024113 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024114 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24115 (ctxt->user_sax->internalSubset != NULL))
24116 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24117 SystemID);
24118}
24119
24120static int
24121isStandaloneSplit(void *ctx)
24122{
Daniel Veillard971771e2005-07-09 17:32:57 +000024123 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024124 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24125 (ctxt->user_sax->isStandalone != NULL))
24126 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24127 return(0);
24128}
24129
24130static int
24131hasInternalSubsetSplit(void *ctx)
24132{
Daniel Veillard971771e2005-07-09 17:32:57 +000024133 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024134 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24135 (ctxt->user_sax->hasInternalSubset != NULL))
24136 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24137 return(0);
24138}
24139
24140static int
24141hasExternalSubsetSplit(void *ctx)
24142{
Daniel Veillard971771e2005-07-09 17:32:57 +000024143 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024144 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24145 (ctxt->user_sax->hasExternalSubset != NULL))
24146 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24147 return(0);
24148}
24149
24150static void
24151externalSubsetSplit(void *ctx, const xmlChar *name,
24152 const xmlChar *ExternalID, const xmlChar *SystemID)
24153{
Daniel Veillard971771e2005-07-09 17:32:57 +000024154 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024155 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24156 (ctxt->user_sax->internalSubset != NULL))
24157 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24158 SystemID);
24159}
24160
24161static xmlParserInputPtr
24162resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24163{
Daniel Veillard971771e2005-07-09 17:32:57 +000024164 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024165 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24166 (ctxt->user_sax->resolveEntity != NULL))
24167 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24168 systemId));
24169 return(NULL);
24170}
24171
24172static xmlEntityPtr
24173getEntitySplit(void *ctx, const xmlChar *name)
24174{
Daniel Veillard971771e2005-07-09 17:32:57 +000024175 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024176 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24177 (ctxt->user_sax->getEntity != NULL))
24178 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24179 return(NULL);
24180}
24181
24182static xmlEntityPtr
24183getParameterEntitySplit(void *ctx, const xmlChar *name)
24184{
Daniel Veillard971771e2005-07-09 17:32:57 +000024185 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024186 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24187 (ctxt->user_sax->getParameterEntity != NULL))
24188 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24189 return(NULL);
24190}
24191
24192
24193static void
24194entityDeclSplit(void *ctx, const xmlChar *name, int type,
24195 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24196{
Daniel Veillard971771e2005-07-09 17:32:57 +000024197 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024198 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24199 (ctxt->user_sax->entityDecl != NULL))
24200 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24201 systemId, content);
24202}
24203
24204static void
24205attributeDeclSplit(void *ctx, const xmlChar * elem,
24206 const xmlChar * name, int type, int def,
24207 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24208{
Daniel Veillard971771e2005-07-09 17:32:57 +000024209 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024210 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24211 (ctxt->user_sax->attributeDecl != NULL)) {
24212 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24213 def, defaultValue, tree);
24214 } else {
24215 xmlFreeEnumeration(tree);
24216 }
24217}
24218
24219static void
24220elementDeclSplit(void *ctx, const xmlChar *name, int type,
24221 xmlElementContentPtr content)
24222{
Daniel Veillard971771e2005-07-09 17:32:57 +000024223 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024224 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24225 (ctxt->user_sax->elementDecl != NULL))
24226 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24227}
24228
24229static void
24230notationDeclSplit(void *ctx, const xmlChar *name,
24231 const xmlChar *publicId, const xmlChar *systemId)
24232{
Daniel Veillard971771e2005-07-09 17:32:57 +000024233 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024234 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24235 (ctxt->user_sax->notationDecl != NULL))
24236 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24237 systemId);
24238}
24239
24240static void
24241unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24242 const xmlChar *publicId, const xmlChar *systemId,
24243 const xmlChar *notationName)
24244{
Daniel Veillard971771e2005-07-09 17:32:57 +000024245 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024246 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24247 (ctxt->user_sax->unparsedEntityDecl != NULL))
24248 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24249 systemId, notationName);
24250}
24251
24252static void
24253setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24254{
Daniel Veillard971771e2005-07-09 17:32:57 +000024255 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024256 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24257 (ctxt->user_sax->setDocumentLocator != NULL))
24258 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24259}
24260
24261static void
24262startDocumentSplit(void *ctx)
24263{
Daniel Veillard971771e2005-07-09 17:32:57 +000024264 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024265 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24266 (ctxt->user_sax->startDocument != NULL))
24267 ctxt->user_sax->startDocument(ctxt->user_data);
24268}
24269
24270static void
24271endDocumentSplit(void *ctx)
24272{
Daniel Veillard971771e2005-07-09 17:32:57 +000024273 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024274 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24275 (ctxt->user_sax->endDocument != NULL))
24276 ctxt->user_sax->endDocument(ctxt->user_data);
24277}
24278
24279static void
24280processingInstructionSplit(void *ctx, const xmlChar *target,
24281 const xmlChar *data)
24282{
Daniel Veillard971771e2005-07-09 17:32:57 +000024283 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024284 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24285 (ctxt->user_sax->processingInstruction != NULL))
24286 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24287}
24288
24289static void
24290commentSplit(void *ctx, const xmlChar *value)
24291{
Daniel Veillard971771e2005-07-09 17:32:57 +000024292 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024293 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24294 (ctxt->user_sax->comment != NULL))
24295 ctxt->user_sax->comment(ctxt->user_data, value);
24296}
24297
24298/*
24299 * Varargs error callbacks to the user application, harder ...
24300 */
24301
24302static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024303warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024304 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024305 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24306 (ctxt->user_sax->warning != NULL)) {
24307 TODO
24308 }
24309}
24310static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024311errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024312 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024313 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24314 (ctxt->user_sax->error != NULL)) {
24315 TODO
24316 }
24317}
24318static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024319fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024320 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024321 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24322 (ctxt->user_sax->fatalError != NULL)) {
24323 TODO
24324 }
24325}
24326
24327/*
24328 * Those are function where both the user handler and the schemas handler
24329 * need to be called.
24330 */
24331static void
24332charactersSplit(void *ctx, const xmlChar *ch, int len)
24333{
Daniel Veillard971771e2005-07-09 17:32:57 +000024334 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024335 if (ctxt == NULL)
24336 return;
24337 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24338 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24339 if (ctxt->ctxt != NULL)
24340 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24341}
24342
24343static void
24344ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24345{
Daniel Veillard971771e2005-07-09 17:32:57 +000024346 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024347 if (ctxt == NULL)
24348 return;
24349 if ((ctxt->user_sax != NULL) &&
24350 (ctxt->user_sax->ignorableWhitespace != NULL))
24351 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24352 if (ctxt->ctxt != NULL)
24353 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24354}
24355
24356static void
24357cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24358{
Daniel Veillard971771e2005-07-09 17:32:57 +000024359 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024360 if (ctxt == NULL)
24361 return;
24362 if ((ctxt->user_sax != NULL) &&
24363 (ctxt->user_sax->ignorableWhitespace != NULL))
24364 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24365 if (ctxt->ctxt != NULL)
24366 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24367}
24368
24369static void
24370referenceSplit(void *ctx, const xmlChar *name)
24371{
Daniel Veillard971771e2005-07-09 17:32:57 +000024372 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024373 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24374 (ctxt->user_sax->reference != NULL))
24375 ctxt->user_sax->reference(ctxt->user_data, name);
24376 if (ctxt->ctxt != NULL)
24377 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24378}
24379
24380static void
24381startElementNsSplit(void *ctx, const xmlChar * localname,
24382 const xmlChar * prefix, const xmlChar * URI,
24383 int nb_namespaces, const xmlChar ** namespaces,
24384 int nb_attributes, int nb_defaulted,
24385 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024386 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024387 if (ctxt == NULL)
24388 return;
24389 if ((ctxt->user_sax != NULL) &&
24390 (ctxt->user_sax->startElementNs != NULL))
24391 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24392 URI, nb_namespaces, namespaces,
24393 nb_attributes, nb_defaulted,
24394 attributes);
24395 if (ctxt->ctxt != NULL)
24396 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24397 URI, nb_namespaces, namespaces,
24398 nb_attributes, nb_defaulted,
24399 attributes);
24400}
24401
24402static void
24403endElementNsSplit(void *ctx, const xmlChar * localname,
24404 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024405 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024406 if (ctxt == NULL)
24407 return;
24408 if ((ctxt->user_sax != NULL) &&
24409 (ctxt->user_sax->endElementNs != NULL))
24410 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24411 if (ctxt->ctxt != NULL)
24412 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24413}
24414
Daniel Veillard4255d502002-04-16 15:50:10 +000024415/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024416 * xmlSchemaSAXPlug:
24417 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024418 * @sax: a pointer to the original xmlSAXHandlerPtr
24419 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024420 *
24421 * Plug a SAX based validation layer in a SAX parsing event flow.
24422 * The original @saxptr and @dataptr data are replaced by new pointers
24423 * but the calls to the original will be maintained.
24424 *
24425 * Returns a pointer to a data structure needed to unplug the validation layer
24426 * or NULL in case of errors.
24427 */
24428xmlSchemaSAXPlugPtr
24429xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24430 xmlSAXHandlerPtr *sax, void **user_data)
24431{
24432 xmlSchemaSAXPlugPtr ret;
24433 xmlSAXHandlerPtr old_sax;
24434
24435 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24436 return(NULL);
24437
24438 /*
24439 * We only allow to plug into SAX2 event streams
24440 */
24441 old_sax = *sax;
24442 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24443 return(NULL);
24444 if ((old_sax != NULL) &&
24445 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24446 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24447 return(NULL);
24448
24449 /*
24450 * everything seems right allocate the local data needed for that layer
24451 */
24452 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24453 if (ret == NULL) {
24454 return(NULL);
24455 }
24456 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24457 ret->magic = XML_SAX_PLUG_MAGIC;
24458 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24459 ret->ctxt = ctxt;
24460 ret->user_sax_ptr = sax;
24461 ret->user_sax = old_sax;
24462 if (old_sax == NULL) {
24463 /*
24464 * go direct, no need for the split block and functions.
24465 */
24466 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24467 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24468 /*
24469 * Note that we use the same text-function for both, to prevent
24470 * the parser from testing for ignorable whitespace.
24471 */
24472 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24473 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24474
24475 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24476 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24477
24478 ret->user_data = ctxt;
24479 *user_data = ctxt;
24480 } else {
24481 /*
24482 * for each callback unused by Schemas initialize it to the Split
24483 * routine only if non NULL in the user block, this can speed up
24484 * things at the SAX level.
24485 */
24486 if (old_sax->internalSubset != NULL)
24487 ret->schemas_sax.internalSubset = internalSubsetSplit;
24488 if (old_sax->isStandalone != NULL)
24489 ret->schemas_sax.isStandalone = isStandaloneSplit;
24490 if (old_sax->hasInternalSubset != NULL)
24491 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24492 if (old_sax->hasExternalSubset != NULL)
24493 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24494 if (old_sax->resolveEntity != NULL)
24495 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24496 if (old_sax->getEntity != NULL)
24497 ret->schemas_sax.getEntity = getEntitySplit;
24498 if (old_sax->entityDecl != NULL)
24499 ret->schemas_sax.entityDecl = entityDeclSplit;
24500 if (old_sax->notationDecl != NULL)
24501 ret->schemas_sax.notationDecl = notationDeclSplit;
24502 if (old_sax->attributeDecl != NULL)
24503 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24504 if (old_sax->elementDecl != NULL)
24505 ret->schemas_sax.elementDecl = elementDeclSplit;
24506 if (old_sax->unparsedEntityDecl != NULL)
24507 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24508 if (old_sax->setDocumentLocator != NULL)
24509 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24510 if (old_sax->startDocument != NULL)
24511 ret->schemas_sax.startDocument = startDocumentSplit;
24512 if (old_sax->endDocument != NULL)
24513 ret->schemas_sax.endDocument = endDocumentSplit;
24514 if (old_sax->processingInstruction != NULL)
24515 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24516 if (old_sax->comment != NULL)
24517 ret->schemas_sax.comment = commentSplit;
24518 if (old_sax->warning != NULL)
24519 ret->schemas_sax.warning = warningSplit;
24520 if (old_sax->error != NULL)
24521 ret->schemas_sax.error = errorSplit;
24522 if (old_sax->fatalError != NULL)
24523 ret->schemas_sax.fatalError = fatalErrorSplit;
24524 if (old_sax->getParameterEntity != NULL)
24525 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24526 if (old_sax->externalSubset != NULL)
24527 ret->schemas_sax.externalSubset = externalSubsetSplit;
24528
24529 /*
24530 * the 6 schemas callback have to go to the splitter functions
24531 * Note that we use the same text-function for ignorableWhitespace
24532 * if possible, to prevent the parser from testing for ignorable
24533 * whitespace.
24534 */
24535 ret->schemas_sax.characters = charactersSplit;
24536 if ((old_sax->ignorableWhitespace != NULL) &&
24537 (old_sax->ignorableWhitespace != old_sax->characters))
24538 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24539 else
24540 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24541 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24542 ret->schemas_sax.reference = referenceSplit;
24543 ret->schemas_sax.startElementNs = startElementNsSplit;
24544 ret->schemas_sax.endElementNs = endElementNsSplit;
24545
24546 ret->user_data_ptr = user_data;
24547 ret->user_data = *user_data;
24548 *user_data = ret;
24549 }
24550
24551 /*
24552 * plug the pointers back.
24553 */
24554 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024555 ctxt->sax = *sax;
24556 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24557 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024558 return(ret);
24559}
24560
24561/**
24562 * xmlSchemaSAXUnplug:
24563 * @plug: a data structure returned by xmlSchemaSAXPlug
24564 *
24565 * Unplug a SAX based validation layer in a SAX parsing event flow.
24566 * The original pointers used in the call are restored.
24567 *
24568 * Returns 0 in case of success and -1 in case of failure.
24569 */
24570int
24571xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24572{
24573 xmlSAXHandlerPtr *sax;
24574 void **user_data;
24575
24576 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24577 return(-1);
24578 plug->magic = 0;
24579
Daniel Veillardf10ae122005-07-10 19:03:16 +000024580 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024581 /* restore the data */
24582 sax = plug->user_sax_ptr;
24583 *sax = plug->user_sax;
24584 if (plug->user_sax != NULL) {
24585 user_data = plug->user_data_ptr;
24586 *user_data = plug->user_data;
24587 }
24588
24589 /* free and return */
24590 xmlFree(plug);
24591 return(0);
24592}
24593
24594/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024595 * xmlSchemaValidateStream:
24596 * @ctxt: a schema validation context
24597 * @input: the input to use for reading the data
24598 * @enc: an optional encoding information
24599 * @sax: a SAX handler for the resulting events
24600 * @user_data: the context to provide to the SAX handler.
24601 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024602 * Validate an input based on a flow of SAX event from the parser
24603 * and forward the events to the @sax handler with the provided @user_data
24604 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024605 *
24606 * Returns 0 if the document is schemas valid, a positive error code
24607 * number otherwise and -1 in case of internal or API error.
24608 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024609int
Daniel Veillard4255d502002-04-16 15:50:10 +000024610xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024611 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24612 xmlSAXHandlerPtr sax, void *user_data)
24613{
Daniel Veillard971771e2005-07-09 17:32:57 +000024614 xmlSchemaSAXPlugPtr plug = NULL;
24615 xmlSAXHandlerPtr old_sax = NULL;
24616 xmlParserCtxtPtr pctxt = NULL;
24617 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024618 int ret;
24619
Daniel Veillard4255d502002-04-16 15:50:10 +000024620 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024621 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024622
Daniel Veillardcdc82732005-07-08 15:04:06 +000024623 /*
24624 * prepare the parser
24625 */
24626 pctxt = xmlNewParserCtxt();
24627 if (pctxt == NULL)
24628 return (-1);
24629 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000024630 pctxt->sax = sax;
24631 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024632#if 0
24633 if (options)
24634 xmlCtxtUseOptions(pctxt, options);
24635#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024636 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024637
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024638 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024639 if (inputStream == NULL) {
24640 ret = -1;
24641 goto done;
24642 }
24643 inputPush(pctxt, inputStream);
24644 ctxt->parserCtxt = pctxt;
24645 ctxt->input = input;
24646
24647 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000024648 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000024649 */
Daniel Veillard971771e2005-07-09 17:32:57 +000024650 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
24651 if (plug == NULL) {
24652 ret = -1;
24653 goto done;
24654 }
24655 ctxt->input = input;
24656 ctxt->enc = enc;
24657 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024658 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24659 ret = xmlSchemaVStart(ctxt);
24660
24661 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24662 ret = ctxt->parserCtxt->errNo;
24663 if (ret == 0)
24664 ret = 1;
24665 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024666
24667done:
Daniel Veillard971771e2005-07-09 17:32:57 +000024668 ctxt->parserCtxt = NULL;
24669 ctxt->sax = NULL;
24670 ctxt->input = NULL;
24671 if (plug != NULL) {
24672 xmlSchemaSAXUnplug(plug);
24673 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024674 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000024675 if (pctxt != NULL) {
24676 pctxt->sax = old_sax;
24677 xmlFreeParserCtxt(pctxt);
24678 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024679 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024680}
24681
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024682/**
24683 * xmlSchemaValidateFile:
24684 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024685 * @filename: the URI of the instance
24686 * @options: a future set of options, currently unused
24687 *
24688 * Do a schemas validation of the given resource, it will use the
24689 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024690 *
24691 * Returns 0 if the document is valid, a positive error code
24692 * number otherwise and -1 in case of an internal or API error.
24693 */
24694int
24695xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024696 const char * filename,
24697 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024698{
Daniel Veillard81562d22005-06-15 13:27:56 +000024699#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024700 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024701 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024702
24703 if ((ctxt == NULL) || (filename == NULL))
24704 return (-1);
24705
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024706 input = xmlParserInputBufferCreateFilename(filename,
24707 XML_CHAR_ENCODING_NONE);
24708 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024709 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024710 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24711 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024712 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024713#else
24714 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024715#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024716}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024717
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024718#define bottom_xmlschemas
24719#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024720#endif /* LIBXML_SCHEMAS_ENABLED */