blob: 1d2af17b8e6aca85e24b6cf67354d229fb010793 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000069#define DUMP_CONTENT_MODEL
70
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000071#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000104 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000105static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000107#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000108static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000109 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000110#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111
Daniel Veillard4255d502002-04-16 15:50:10 +0000112#define IS_SCHEMA(node, type) \
113 ((node != NULL) && (node->ns != NULL) && \
114 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
115 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
116
Daniel Veillardc0826a72004-08-10 14:17:33 +0000117#define FREE_AND_NULL(str) \
118 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000119 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120 str = NULL; \
121 }
122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000123#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000124 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
125 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000126
127#define IS_COMPLEX_TYPE(item) \
128 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
129 (item->builtInType == XML_SCHEMAS_ANYTYPE))
130
131#define IS_SIMPLE_TYPE(item) \
132 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
133 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000134 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000136#define IS_ANY_SIMPLE_TYPE(item) \
137 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000138 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000139
140#define IS_NOT_TYPEFIXED(item) \
141 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
142 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
143
144#define HAS_COMPLEX_CONTENT(item) \
145 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
146 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
147 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
148
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000149#define HAS_SIMPLE_CONTENT(item) \
150 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
151 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
152
153#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
154
155#define IS_PARTICLE_EMPTIABLE(item) \
156 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000158#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000160#define GET_LIST_ITEM_TYPE(item) item->subtypes
161
162#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
163#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
164#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000166#define IS_MODEL_GROUP(item) \
167 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
168 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
169 (item->type == XML_SCHEMA_TYPE_ALL))
170
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000171#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
172
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000173#define ELEM_TYPE(item) item->subtypes
174
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000175#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000177#define SUBST_GROUP_AFF(item) item->refDecl
178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000179#if 0
180#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
181#endif
182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000183#define SUBSET_RESTRICTION 1<<0
184#define SUBSET_EXTENSION 1<<1
185#define SUBSET_SUBSTITUTION 1<<2
186#define SUBSET_LIST 1<<3
187#define SUBSET_UNION 1<<4
188
Daniel Veillard4255d502002-04-16 15:50:10 +0000189#define XML_SCHEMAS_PARSE_ERROR 1
190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000193typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
194typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000199
200typedef struct _xmlSchemaItemList xmlSchemaItemList;
201typedef xmlSchemaItemList *xmlSchemaItemListPtr;
202
203struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000204 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 int nbItems; /* used for dynamic addition of schemata */
206 int sizeItems; /* used for dynamic addition of schemata */
207};
208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000209typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
210typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
211struct _xmlSchemaAbstractCtxt {
212 int type;
213};
214
215#define XML_SCHEMA_CTXT_PARSER 1
216#define XML_SCHEMA_CTXT_VALIDATOR 2
217
Daniel Veillard4255d502002-04-16 15:50:10 +0000218struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000219 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 void *userData; /* user specific data block */
221 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
222 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000223 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000227 xmlSchemaPtr topschema; /* The main schema */
228 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000231 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 int counter;
233
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000234 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000236 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 const char *buffer;
239 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241 /*
242 * Used to build complex element content models
243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245 xmlAutomataStatePtr start;
246 xmlAutomataStatePtr end;
247 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000248
249 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000250 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000251 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
252 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 xmlSchemaAssemblePtr assemble;
254 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000256 const xmlChar **localImports; /* list of locally imported namespaces */
257 int sizeLocalImports;
258 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000259 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000260 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000261};
262
Daniel Veillard4255d502002-04-16 15:50:10 +0000263#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000267#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
269#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000270#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000271#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
273#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
274#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
275#define XML_SCHEMAS_ATTR_WILD_SKIP 13
276#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
277#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
278#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
279#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281/**
282 * xmlSchemaBasicItem:
283 *
284 * The abstract base type for schema components.
285 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000286typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
287typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
288struct _xmlSchemaBasicItem {
289 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000290};
291
292/**
293 * xmlSchemaAnnotItem:
294 *
295 * The abstract base type for annotated schema components.
296 * (Extends xmlSchemaBasicItem)
297 */
298typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
299typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
300struct _xmlSchemaAnnotItem {
301 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000302 xmlSchemaAnnotPtr annot;
303};
304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000305/**
306 * xmlSchemaTreeItem:
307 *
308 * The abstract base type for tree-like structured schema components.
309 * (Extends xmlSchemaAnnotItem)
310 */
311typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
312typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
313struct _xmlSchemaTreeItem {
314 xmlSchemaTypeType type;
315 xmlSchemaAnnotPtr annot;
316 xmlSchemaTreeItemPtr next;
317 xmlSchemaTreeItemPtr children;
318};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000320/**
321 * xmlSchemaQNameRef:
322 *
323 * A component reference item (not a schema component)
324 * (Extends xmlSchemaBasicItem)
325 */
326typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
327typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
328struct _xmlSchemaQNameRef {
329 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000331 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000332 const xmlChar *name;
333 const xmlChar *targetNamespace;
334};
335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000336/**
337 * xmlSchemaParticle:
338 *
339 * A particle component.
340 * (Extends xmlSchemaTreeItem)
341 */
342typedef struct _xmlSchemaParticle xmlSchemaParticle;
343typedef xmlSchemaParticle *xmlSchemaParticlePtr;
344struct _xmlSchemaParticle {
345 xmlSchemaTypeType type;
346 xmlSchemaAnnotPtr annot;
347 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
348 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
349 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000350 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351 xmlNodePtr node;
352};
353
354/**
355 * xmlSchemaModelGroup:
356 *
357 * A model group component.
358 * (Extends xmlSchemaTreeItem)
359 */
360typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next; /* not used */
366 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
367 xmlNodePtr node;
368};
369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000370#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000371/**
372 * xmlSchemaModelGroupDef:
373 *
374 * A model group definition component.
375 * (Extends xmlSchemaTreeItem)
376 */
377typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
378typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
379struct _xmlSchemaModelGroupDef {
380 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
381 xmlSchemaAnnotPtr annot;
382 xmlSchemaTreeItemPtr next; /* not used */
383 xmlSchemaTreeItemPtr children; /* the "model group" */
384 const xmlChar *name;
385 const xmlChar *targetNamespace;
386 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000387 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388};
389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390typedef struct _xmlSchemaIDC xmlSchemaIDC;
391typedef xmlSchemaIDC *xmlSchemaIDCPtr;
392
393/**
394 * xmlSchemaIDCSelect:
395 *
396 * The identity-constraint "field" and "selector" item, holding the
397 * XPath expression.
398 */
399typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
400typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000401struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402 xmlSchemaIDCSelectPtr next;
403 xmlSchemaIDCPtr idc;
404 int index; /* an index position if significant for IDC key-sequences */
405 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000406 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000407};
408
409/**
410 * xmlSchemaIDC:
411 *
412 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000413 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000414 */
415
416struct _xmlSchemaIDC {
417 xmlSchemaTypeType type;
418 xmlSchemaAnnotPtr annot;
419 xmlSchemaIDCPtr next;
420 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 const xmlChar *targetNamespace;
423 xmlSchemaIDCSelectPtr selector;
424 xmlSchemaIDCSelectPtr fields;
425 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000426 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000427};
428
429/**
430 * xmlSchemaIDCAug:
431 *
432 * The augmented IDC information used for validation.
433 */
434typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
435typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
436struct _xmlSchemaIDCAug {
437 xmlSchemaIDCAugPtr next; /* next in a list */
438 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000439 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000440 tables need to be bubbled upwards */
441};
442
443/**
444 * xmlSchemaPSVIIDCKeySequence:
445 *
446 * The key sequence of a node table item.
447 */
448typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
449typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
450struct _xmlSchemaPSVIIDCKey {
451 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000452 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453};
454
455/**
456 * xmlSchemaPSVIIDCNode:
457 *
458 * The node table item of a node table.
459 */
460typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
461typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
462struct _xmlSchemaPSVIIDCNode {
463 xmlNodePtr node;
464 xmlSchemaPSVIIDCKeyPtr *keys;
465};
466
467/**
468 * xmlSchemaPSVIIDCBinding:
469 *
470 * The identity-constraint binding item of the [identity-constraint table].
471 */
472typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
473typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
474struct _xmlSchemaPSVIIDCBinding {
475 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
476 xmlSchemaIDCPtr definition; /* the IDC definition */
477 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
478 int nbNodes; /* number of entries in the node table */
479 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000480 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 table */
482 /* int nbKeys; number of keys in each key-sequence */
483};
484
485#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
486#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
487
488#define XPATH_STATE_OBJ_MATCHES -2
489#define XPATH_STATE_OBJ_BLOCKED -3
490
491typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
492typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
493
494/**
495 * xmlSchemaIDCStateObj:
496 *
497 * The state object used to evaluate XPath expressions.
498 */
499typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
500typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
501struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000502 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000504 int depth; /* depth of creation */
505 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 int nbHistory;
507 int sizeHistory;
508 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
509 matcher */
510 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000511 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000512};
513
514#define IDC_MATCHER 0
515
516/**
517 * xmlSchemaIDCMatcher:
518 *
519 * Used to IDC selectors (and fields) successively.
520 */
521struct _xmlSchemaIDCMatcher {
522 int type;
523 int depth; /* the tree depth at creation time */
524 xmlSchemaIDCMatcherPtr next; /* next in the list */
525 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
526 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
527 elements */
528 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 int targetDepth;
530};
531
532/*
533* Element info flags.
534*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
536#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
537#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
538#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
539
540#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
541#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
542#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
543
544#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
545#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
546#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
547#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548
549/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000550 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 *
552 * Holds information of an element node.
553 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000554struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000557 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 const xmlChar *nsName;
559 const xmlChar *value;
560 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000562 int flags; /* combination of node info flags */
563 int valNeeded;
564 int normVal;
565
566 xmlSchemaElementPtr decl; /* the element/attribute declaration */
567 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
569 for the scope element*/
570 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
571 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000572 xmlRegExecCtxtPtr regexCtxt;
573
574 const xmlChar **nsBindings; /* Namespace bindings on this element */
575 int nbNsBindings;
576 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000577};
578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000579/*
580* @metaType values of xmlSchemaAttrInfo.
581*/
582#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
584#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
585#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
586#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
589typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
590struct _xmlSchemaAttrInfo {
591 xmlNodePtr node;
592 int nodeType;
593 const xmlChar *localName;
594 const xmlChar *nsName;
595 const xmlChar *value;
596 xmlSchemaValPtr val; /* the pre-computed value if any */
597 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
598 int flags; /* combination of node info flags */
599
600 xmlSchemaAttributePtr decl; /* the attribute declaration */
601 xmlSchemaAttributePtr use; /* the attribute use */
602 int state;
603 int metaType;
604 const xmlChar *vcValue; /* the value constraint value */
605 xmlSchemaNodeInfoPtr parent;
606};
607
608
609#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000610/**
611 * xmlSchemaValidCtxt:
612 *
613 * A Schemas validation context
614 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000615struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *userData; /* user specific data block */
618 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000619 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000621
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 xmlSchemaPtr schema; /* The schema in use */
623 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 xmlCharEncoding enc;
626 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000627 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000629
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 int err;
631 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000632
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000633 xmlNodePtr node;
634 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000635 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637 xmlRegExecCtxtPtr regexp;
638 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000639
Daniel Veillardc0826a72004-08-10 14:17:33 +0000640 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000641 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000642 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000643 xmlSchemaParserCtxtPtr pctxt;
644 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000647 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000649 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
652
653 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
654 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000655
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
657 int nbIdcNodes;
658 int sizeIdcNodes;
659
660 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
661 int nbIdcKeys;
662 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000663
664 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000665
666 xmlDictPtr dict;
667
Daniel Veillard39e5c892005-07-03 22:48:50 +0000668#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000670#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671
672 xmlSchemaAttrInfoPtr *attrInfos;
673 int nbAttrInfos;
674 int sizeAttrInfos;
675
676 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000677};
678
Daniel Veillard1d913862003-11-21 00:28:39 +0000679/*
680 * These are the entries in the schemas importSchemas hash table
681 */
682typedef struct _xmlSchemaImport xmlSchemaImport;
683typedef xmlSchemaImport *xmlSchemaImportPtr;
684struct _xmlSchemaImport {
685 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000686 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000687 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000688 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000689};
Daniel Veillard4255d502002-04-16 15:50:10 +0000690
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000691/*
692 * These are the entries associated to includes in a schemas
693 */
694typedef struct _xmlSchemaInclude xmlSchemaInclude;
695typedef xmlSchemaInclude *xmlSchemaIncludePtr;
696struct _xmlSchemaInclude {
697 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698 const xmlChar *schemaLocation;
699 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000700 const xmlChar *origTargetNamespace;
701 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000702};
703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000704/**
705 * xmlSchemaSubstGroup:
706 *
707 *
708 */
709typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
710typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
711struct _xmlSchemaSubstGroup {
712 xmlSchemaElementPtr head;
713 xmlSchemaItemListPtr members;
714};
715
Daniel Veillard4255d502002-04-16 15:50:10 +0000716/************************************************************************
717 * *
718 * Some predeclarations *
719 * *
720 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000722static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
723 xmlSchemaPtr schema,
724 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725static void
726xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
727 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000728static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000729xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
730static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000731xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
732 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000733static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000734xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
735 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000736static void
737xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000738static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000739xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740static xmlSchemaTreeItemPtr
741xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
742 xmlNodePtr node, xmlSchemaTypeType type,
743 int withParticle);
744static const xmlChar *
745xmlSchemaCompTypeToString(xmlSchemaTypeType type);
746static xmlSchemaTypeLinkPtr
747xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748static void
749xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
750 const char *funcName,
751 const char *message);
752static int
753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
754 xmlSchemaTypePtr baseType,
755 int subset);
756static void
757xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
758 xmlSchemaParserCtxtPtr ctxt,
759 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000760
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761/************************************************************************
762 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000763 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 * *
765 ************************************************************************/
766
767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000768 * xmlSchemaCompTypeToString:
769 * @type: the type of the schema item
770 *
771 * Returns the component name of a schema item.
772 */
773static const xmlChar *
774xmlSchemaCompTypeToString(xmlSchemaTypeType type)
775{
776 switch (type) {
777 case XML_SCHEMA_TYPE_SIMPLE:
778 return(BAD_CAST "simple type definition");
779 case XML_SCHEMA_TYPE_COMPLEX:
780 return(BAD_CAST "complex type definition");
781 case XML_SCHEMA_TYPE_ELEMENT:
782 return(BAD_CAST "element declaration");
783 case XML_SCHEMA_TYPE_ATTRIBUTE:
784 return(BAD_CAST "attribute declaration");
785 case XML_SCHEMA_TYPE_GROUP:
786 return(BAD_CAST "model group definition");
787 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
788 return(BAD_CAST "attribute group definition");
789 case XML_SCHEMA_TYPE_NOTATION:
790 return(BAD_CAST "notation declaration");
791 case XML_SCHEMA_TYPE_SEQUENCE:
792 return(BAD_CAST "model group (sequence)");
793 case XML_SCHEMA_TYPE_CHOICE:
794 return(BAD_CAST "model group (choice)");
795 case XML_SCHEMA_TYPE_ALL:
796 return(BAD_CAST "model group (all)");
797 case XML_SCHEMA_TYPE_PARTICLE:
798 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000799 case XML_SCHEMA_TYPE_IDC_UNIQUE:
800 return(BAD_CAST "IDC (unique)");
801 case XML_SCHEMA_TYPE_IDC_KEY:
802 return(BAD_CAST "IDC (key)");
803 case XML_SCHEMA_TYPE_IDC_KEYREF:
804 return(BAD_CAST "IDC (keyref)");
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +0000805 case XML_SCHEMA_TYPE_ANY:
806 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000807 case XML_SCHEMA_EXTRA_QNAMEREF:
808 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000809 default:
810 return(BAD_CAST "Not a schema component");
811 }
812}
813
814/**
815 * xmlSchemaGetComponentNode:
816 * @item: a schema component
817 *
818 * Returns node associated with the schema component.
819 * NOTE that such a node need not be available; plus, a component's
820 * node need not to reflect the component directly, since there is no
821 * one-to-one relationship between the XML Schema representation and
822 * the component representation.
823 */
824static xmlNodePtr
825xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
826{
827 switch (item->type) {
828 case XML_SCHEMA_TYPE_ELEMENT:
829 return (((xmlSchemaElementPtr) item)->node);
830 case XML_SCHEMA_TYPE_ATTRIBUTE:
831 return (((xmlSchemaAttributePtr) item)->node);
832 case XML_SCHEMA_TYPE_COMPLEX:
833 case XML_SCHEMA_TYPE_SIMPLE:
834 return (((xmlSchemaTypePtr) item)->node);
835 case XML_SCHEMA_TYPE_ANY:
836 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
837 return (((xmlSchemaWildcardPtr) item)->node);
838 case XML_SCHEMA_TYPE_PARTICLE:
839 return (((xmlSchemaParticlePtr) item)->node);
840 case XML_SCHEMA_TYPE_SEQUENCE:
841 case XML_SCHEMA_TYPE_CHOICE:
842 case XML_SCHEMA_TYPE_ALL:
843 return (((xmlSchemaModelGroupPtr) item)->node);
844 case XML_SCHEMA_TYPE_GROUP:
845 return (((xmlSchemaModelGroupDefPtr) item)->node);
846 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
847 return (((xmlSchemaAttributeGroupPtr) item)->node);
848 case XML_SCHEMA_TYPE_IDC_UNIQUE:
849 case XML_SCHEMA_TYPE_IDC_KEY:
850 case XML_SCHEMA_TYPE_IDC_KEYREF:
851 return (((xmlSchemaIDCPtr) item)->node);
852 default:
853 return (NULL);
854 }
855}
856
857#if 0
858/**
859 * xmlSchemaGetNextComponent:
860 * @item: a schema component
861 *
862 * Returns the next sibling of the schema component.
863 */
864static xmlSchemaBasicItemPtr
865xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
866{
867 switch (item->type) {
868 case XML_SCHEMA_TYPE_ELEMENT:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
870 case XML_SCHEMA_TYPE_ATTRIBUTE:
871 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
872 case XML_SCHEMA_TYPE_COMPLEX:
873 case XML_SCHEMA_TYPE_SIMPLE:
874 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
875 case XML_SCHEMA_TYPE_ANY:
876 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
877 return (NULL);
878 case XML_SCHEMA_TYPE_PARTICLE:
879 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
880 case XML_SCHEMA_TYPE_SEQUENCE:
881 case XML_SCHEMA_TYPE_CHOICE:
882 case XML_SCHEMA_TYPE_ALL:
883 return (NULL);
884 case XML_SCHEMA_TYPE_GROUP:
885 return (NULL);
886 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
887 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
888 case XML_SCHEMA_TYPE_IDC_UNIQUE:
889 case XML_SCHEMA_TYPE_IDC_KEY:
890 case XML_SCHEMA_TYPE_IDC_KEYREF:
891 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
892 default:
893 return (NULL);
894 }
895}
896#endif
897
898/**
899 * xmlSchemaGetAttrName:
900 * @attr: the attribute declaration/use
901 *
902 * Returns the name of the attribute; if the attribute
903 * is a reference, the name of the referenced global type will be returned.
904 */
905static const xmlChar *
906xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
907{
908 if (attr->ref != NULL)
909 return(attr->ref);
910 else
911 return(attr->name);
912}
913
914/**
915 * xmlSchemaGetAttrTargetNsURI:
916 * @type: the type (element or attribute)
917 *
918 * Returns the target namespace URI of the type; if the type is a reference,
919 * the target namespace of the referenced type will be returned.
920 */
921static const xmlChar *
922xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
923{
924 if (attr->ref != NULL)
925 return (attr->refNs);
926 else
927 return(attr->targetNamespace);
928}
929
930/**
931 * xmlSchemaFormatQName:
932 * @buf: the string buffer
933 * @namespaceName: the namespace name
934 * @localName: the local name
935 *
936 * Returns the given QName in the format "{namespaceName}localName" or
937 * just "localName" if @namespaceName is NULL.
938 *
939 * Returns the localName if @namespaceName is NULL, a formatted
940 * string otherwise.
941 */
942static const xmlChar*
943xmlSchemaFormatQName(xmlChar **buf,
944 const xmlChar *namespaceName,
945 const xmlChar *localName)
946{
947 FREE_AND_NULL(*buf)
948 if (namespaceName == NULL)
949 return(localName);
950
951 *buf = xmlStrdup(BAD_CAST "{");
952 *buf = xmlStrcat(*buf, namespaceName);
953 *buf = xmlStrcat(*buf, BAD_CAST "}");
954 *buf = xmlStrcat(*buf, localName);
955
956 return ((const xmlChar *) *buf);
957}
958
959static const xmlChar*
960xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
961{
962 if (ns != NULL)
963 return (xmlSchemaFormatQName(buf, ns->href, localName));
964 else
965 return (xmlSchemaFormatQName(buf, NULL, localName));
966}
967
968static const xmlChar *
969xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
970{
971 switch (item->type) {
972 case XML_SCHEMA_TYPE_ELEMENT:
973 return (((xmlSchemaElementPtr) item)->name);
974 case XML_SCHEMA_TYPE_ATTRIBUTE:
975 return (((xmlSchemaAttributePtr) item)->name);
976 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
977 return (((xmlSchemaAttributeGroupPtr) item)->name);
978 case XML_SCHEMA_TYPE_BASIC:
979 case XML_SCHEMA_TYPE_SIMPLE:
980 case XML_SCHEMA_TYPE_COMPLEX:
981 return (((xmlSchemaTypePtr) item)->name);
982 case XML_SCHEMA_TYPE_GROUP:
983 return (((xmlSchemaModelGroupDefPtr) item)->name);
984 case XML_SCHEMA_TYPE_IDC_KEY:
985 case XML_SCHEMA_TYPE_IDC_UNIQUE:
986 case XML_SCHEMA_TYPE_IDC_KEYREF:
987 return (((xmlSchemaIDCPtr) item)->name);
988 default:
989 /*
990 * Other components cannot have names.
991 */
992 break;
993 }
994 return (NULL);
995}
996
997static const xmlChar *
998xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
999{
1000 switch (item->type) {
1001 case XML_SCHEMA_TYPE_ELEMENT:
1002 return (((xmlSchemaElementPtr) item)->targetNamespace);
1003 case XML_SCHEMA_TYPE_ATTRIBUTE:
1004 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1005 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1006 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1007 case XML_SCHEMA_TYPE_BASIC:
1008 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1009 case XML_SCHEMA_TYPE_SIMPLE:
1010 case XML_SCHEMA_TYPE_COMPLEX:
1011 return (((xmlSchemaTypePtr) item)->targetNamespace);
1012 case XML_SCHEMA_TYPE_GROUP:
1013 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1014 case XML_SCHEMA_TYPE_IDC_KEY:
1015 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1016 case XML_SCHEMA_TYPE_IDC_KEYREF:
1017 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1018 default:
1019 /*
1020 * Other components cannot have names.
1021 */
1022 break;
1023 }
1024 return (NULL);
1025}
1026
1027static const xmlChar*
1028xmlSchemaGetComponentQName(xmlChar **buf,
1029 void *item)
1030{
1031 return (xmlSchemaFormatQName(buf,
1032 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1033 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1034}
1035
1036/**
1037 * xmlSchemaWildcardPCToString:
1038 * @pc: the type of processContents
1039 *
1040 * Returns a string representation of the type of
1041 * processContents.
1042 */
1043static const xmlChar *
1044xmlSchemaWildcardPCToString(int pc)
1045{
1046 switch (pc) {
1047 case XML_SCHEMAS_ANY_SKIP:
1048 return (BAD_CAST "skip");
1049 case XML_SCHEMAS_ANY_LAX:
1050 return (BAD_CAST "lax");
1051 case XML_SCHEMAS_ANY_STRICT:
1052 return (BAD_CAST "strict");
1053 default:
1054 return (BAD_CAST "invalid process contents");
1055 }
1056}
1057
1058/**
1059 * xmlSchemaGetCanonValueWhtspExt:
1060 * @val: the precomputed value
1061 * @retValue: the returned value
1062 * @ws: the whitespace type of the value
1063 *
1064 * Get a the cononical representation of the value.
1065 * The caller has to free the returned retValue.
1066 *
1067 * Returns 0 if the value could be built and -1 in case of
1068 * API errors or if the value type is not supported yet.
1069 */
1070static int
1071xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1072 xmlSchemaWhitespaceValueType ws,
1073 xmlChar **retValue)
1074{
1075 int list;
1076 xmlSchemaValType valType;
1077 const xmlChar *value, *value2 = NULL;
1078
1079
1080 if ((retValue == NULL) || (val == NULL))
1081 return (-1);
1082 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1083 *retValue = NULL;
1084 do {
1085 value = NULL;
1086 valType = xmlSchemaGetValType(val);
1087 switch (valType) {
1088 case XML_SCHEMAS_STRING:
1089 case XML_SCHEMAS_NORMSTRING:
1090 case XML_SCHEMAS_ANYSIMPLETYPE:
1091 value = xmlSchemaValueGetAsString(val);
1092 if (value != NULL) {
1093 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1094 value2 = xmlSchemaCollapseString(value);
1095 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1096 value2 = xmlSchemaWhiteSpaceReplace(value);
1097 if (value2 != NULL)
1098 value = value2;
1099 }
1100 break;
1101 default:
1102 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1103 if (value2 != NULL)
1104 xmlFree((xmlChar *) value2);
1105 goto internal_error;
1106 }
1107 value = value2;
1108 }
1109 if (*retValue == NULL)
1110 if (value == NULL) {
1111 if (! list)
1112 *retValue = xmlStrdup(BAD_CAST "");
1113 } else
1114 *retValue = xmlStrdup(value);
1115 else if (value != NULL) {
1116 /* List. */
1117 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1118 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1119 }
1120 FREE_AND_NULL(value2)
1121 val = xmlSchemaValueGetNext(val);
1122 } while (val != NULL);
1123
1124 return (0);
1125internal_error:
1126 if (*retValue != NULL)
1127 xmlFree((xmlChar *) (*retValue));
1128 if (value2 != NULL)
1129 xmlFree((xmlChar *) value2);
1130 return (-1);
1131}
1132
1133/**
1134 * xmlSchemaFormatItemForReport:
1135 * @buf: the string buffer
1136 * @itemDes: the designation of the item
1137 * @itemName: the name of the item
1138 * @item: the item as an object
1139 * @itemNode: the node of the item
1140 * @local: the local name
1141 * @parsing: if the function is used during the parse
1142 *
1143 * Returns a representation of the given item used
1144 * for error reports.
1145 *
1146 * The following order is used to build the resulting
1147 * designation if the arguments are not NULL:
1148 * 1a. If itemDes not NULL -> itemDes
1149 * 1b. If (itemDes not NULL) and (itemName not NULL)
1150 * -> itemDes + itemName
1151 * 2. If the preceding was NULL and (item not NULL) -> item
1152 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1153 *
1154 * If the itemNode is an attribute node, the name of the attribute
1155 * will be appended to the result.
1156 *
1157 * Returns the formatted string and sets @buf to the resulting value.
1158 */
1159static xmlChar*
1160xmlSchemaFormatItemForReport(xmlChar **buf,
1161 const xmlChar *itemDes,
1162 xmlSchemaTypePtr item,
1163 xmlNodePtr itemNode)
1164{
1165 xmlChar *str = NULL;
1166 int named = 1;
1167
1168 if (*buf != NULL) {
1169 xmlFree(*buf);
1170 *buf = NULL;
1171 }
1172
1173 if (itemDes != NULL) {
1174 *buf = xmlStrdup(itemDes);
1175 } else if (item != NULL) {
1176 switch (item->type) {
1177 case XML_SCHEMA_TYPE_BASIC:
1178 if (VARIETY_ATOMIC(item))
1179 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1180 else if (VARIETY_LIST(item))
1181 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1182 else if (VARIETY_UNION(item))
1183 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1184 else
1185 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1186 *buf = xmlStrcat(*buf, item->name);
1187 *buf = xmlStrcat(*buf, BAD_CAST "'");
1188 break;
1189 case XML_SCHEMA_TYPE_SIMPLE:
1190 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1191 *buf = xmlStrdup(BAD_CAST"");
1192 } else {
1193 *buf = xmlStrdup(BAD_CAST "local ");
1194 }
1195 if (VARIETY_ATOMIC(item))
1196 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1197 else if (VARIETY_LIST(item))
1198 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1199 else if (VARIETY_UNION(item))
1200 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1201 else
1202 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1203 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1204 *buf = xmlStrcat(*buf, BAD_CAST " '");
1205 *buf = xmlStrcat(*buf, item->name);
1206 *buf = xmlStrcat(*buf, BAD_CAST "'");
1207 }
1208 break;
1209 case XML_SCHEMA_TYPE_COMPLEX:
1210 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1211 *buf = xmlStrdup(BAD_CAST "");
1212 else
1213 *buf = xmlStrdup(BAD_CAST "local ");
1214 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1215 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1216 *buf = xmlStrcat(*buf, BAD_CAST " '");
1217 *buf = xmlStrcat(*buf, item->name);
1218 *buf = xmlStrcat(*buf, BAD_CAST "'");
1219 }
1220 break;
1221 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1222 xmlSchemaAttributePtr attr;
1223
1224 attr = (xmlSchemaAttributePtr) item;
1225 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1226 (attr->ref == NULL)) {
1227 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1228 *buf = xmlStrcat(*buf, BAD_CAST " '");
1229 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1230 attr->targetNamespace, attr->name));
1231 FREE_AND_NULL(str)
1232 *buf = xmlStrcat(*buf, BAD_CAST "'");
1233 } else {
1234 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1235 *buf = xmlStrcat(*buf, BAD_CAST " '");
1236 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1237 attr->refNs, attr->ref));
1238 FREE_AND_NULL(str)
1239 *buf = xmlStrcat(*buf, BAD_CAST "'");
1240 }
1241 }
1242 break;
1243 case XML_SCHEMA_TYPE_ELEMENT: {
1244 xmlSchemaElementPtr elem;
1245
1246 elem = (xmlSchemaElementPtr) item;
1247 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1248 (elem->ref == NULL)) {
1249 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1250 *buf = xmlStrcat(*buf, BAD_CAST " '");
1251 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1252 elem->targetNamespace, elem->name));
1253 *buf = xmlStrcat(*buf, BAD_CAST "'");
1254 }
1255 }
1256 break;
1257 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1258 case XML_SCHEMA_TYPE_IDC_KEY:
1259 case XML_SCHEMA_TYPE_IDC_KEYREF:
1260 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1261 *buf = xmlStrdup(BAD_CAST "unique '");
1262 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1263 *buf = xmlStrdup(BAD_CAST "key '");
1264 else
1265 *buf = xmlStrdup(BAD_CAST "keyRef '");
1266 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1267 *buf = xmlStrcat(*buf, BAD_CAST "'");
1268 break;
1269 case XML_SCHEMA_TYPE_ANY:
1270 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1271 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1272 ((xmlSchemaWildcardPtr) item)->processContents));
1273 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1274 break;
1275 case XML_SCHEMA_FACET_MININCLUSIVE:
1276 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1277 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1278 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1279 case XML_SCHEMA_FACET_TOTALDIGITS:
1280 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1281 case XML_SCHEMA_FACET_PATTERN:
1282 case XML_SCHEMA_FACET_ENUMERATION:
1283 case XML_SCHEMA_FACET_WHITESPACE:
1284 case XML_SCHEMA_FACET_LENGTH:
1285 case XML_SCHEMA_FACET_MAXLENGTH:
1286 case XML_SCHEMA_FACET_MINLENGTH:
1287 *buf = xmlStrdup(BAD_CAST "facet '");
1288 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1289 *buf = xmlStrcat(*buf, BAD_CAST "'");
1290 break;
1291 case XML_SCHEMA_TYPE_NOTATION:
1292 *buf = xmlStrdup(BAD_CAST "notation");
1293 break;
1294 case XML_SCHEMA_TYPE_GROUP: {
1295 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1296 *buf = xmlStrcat(*buf, BAD_CAST " '");
1297 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1298 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1299 ((xmlSchemaModelGroupDefPtr) item)->name));
1300 *buf = xmlStrcat(*buf, BAD_CAST "'");
1301 FREE_AND_NULL(str)
1302 }
1303 break;
1304 case XML_SCHEMA_TYPE_SEQUENCE:
1305 case XML_SCHEMA_TYPE_CHOICE:
1306 case XML_SCHEMA_TYPE_ALL:
1307 case XML_SCHEMA_TYPE_PARTICLE:
1308 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1309 break;
1310 default:
1311 named = 0;
1312 }
1313 } else
1314 named = 0;
1315
1316 if ((named == 0) && (itemNode != NULL)) {
1317 xmlNodePtr elem;
1318
1319 if (itemNode->type == XML_ATTRIBUTE_NODE)
1320 elem = itemNode->parent;
1321 else
1322 elem = itemNode;
1323 *buf = xmlStrdup(BAD_CAST "Element '");
1324 if (elem->ns != NULL) {
1325 *buf = xmlStrcat(*buf,
1326 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1327 FREE_AND_NULL(str)
1328 } else
1329 *buf = xmlStrcat(*buf, elem->name);
1330 *buf = xmlStrcat(*buf, BAD_CAST "'");
1331
1332 }
1333 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1334 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1335 if (itemNode->ns != NULL) {
1336 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1337 itemNode->ns->href, itemNode->name));
1338 FREE_AND_NULL(str)
1339 } else
1340 *buf = xmlStrcat(*buf, itemNode->name);
1341 *buf = xmlStrcat(*buf, BAD_CAST "'");
1342 }
1343 FREE_AND_NULL(str)
1344
1345 return (*buf);
1346}
1347
1348/**
1349 * xmlSchemaFormatFacetEnumSet:
1350 * @buf: the string buffer
1351 * @type: the type holding the enumeration facets
1352 *
1353 * Builds a string consisting of all enumeration elements.
1354 *
1355 * Returns a string of all enumeration elements.
1356 */
1357static const xmlChar *
1358xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1359 xmlChar **buf, xmlSchemaTypePtr type)
1360{
1361 xmlSchemaFacetPtr facet;
1362 xmlSchemaWhitespaceValueType ws;
1363 xmlChar *value = NULL;
1364 int res;
1365
1366 if (*buf != NULL)
1367 xmlFree(*buf);
1368 *buf = NULL;
1369
1370 do {
1371 /*
1372 * Use the whitespace type of the base type.
1373 */
1374 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1375 for (facet = type->facets; facet != NULL; facet = facet->next) {
1376 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1377 continue;
1378 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1379 ws, &value);
1380 if (res == -1) {
1381 xmlSchemaInternalErr(actxt,
1382 "xmlSchemaFormatFacetEnumSet",
1383 "compute the canonical lexical representation");
1384 if (*buf != NULL)
1385 xmlFree(*buf);
1386 *buf = NULL;
1387 return (NULL);
1388 }
1389 if (*buf == NULL)
1390 *buf = xmlStrdup(BAD_CAST "'");
1391 else
1392 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1393 *buf = xmlStrcat(*buf, BAD_CAST value);
1394 *buf = xmlStrcat(*buf, BAD_CAST "'");
1395 if (value != NULL) {
1396 xmlFree((xmlChar *)value);
1397 value = NULL;
1398 }
1399 }
1400 type = type->baseType;
1401 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1402
1403 return ((const xmlChar *) *buf);
1404}
1405
1406/************************************************************************
1407 * *
1408 * Error functions *
1409 * *
1410 ************************************************************************/
1411
1412#if 0
1413static void
1414xmlSchemaErrMemory(const char *msg)
1415{
1416 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1417 msg);
1418}
1419#endif
1420
1421/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001422 * xmlSchemaPErrMemory:
1423 * @node: a context node
1424 * @extra: extra informations
1425 *
1426 * Handle an out of memory condition
1427 */
1428static void
1429xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1430 const char *extra, xmlNodePtr node)
1431{
1432 if (ctxt != NULL)
1433 ctxt->nberrors++;
1434 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1435 extra);
1436}
1437
1438/**
1439 * xmlSchemaPErr:
1440 * @ctxt: the parsing context
1441 * @node: the context node
1442 * @error: the error code
1443 * @msg: the error message
1444 * @str1: extra data
1445 * @str2: extra data
1446 *
1447 * Handle a parser error
1448 */
1449static void
1450xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1451 const char *msg, const xmlChar * str1, const xmlChar * str2)
1452{
1453 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001454 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001455 void *data = NULL;
1456
1457 if (ctxt != NULL) {
1458 ctxt->nberrors++;
1459 channel = ctxt->error;
1460 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001461 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001462 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001463 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001464 error, XML_ERR_ERROR, NULL, 0,
1465 (const char *) str1, (const char *) str2, NULL, 0, 0,
1466 msg, str1, str2);
1467}
1468
1469/**
1470 * xmlSchemaPErr2:
1471 * @ctxt: the parsing context
1472 * @node: the context node
1473 * @node: the current child
1474 * @error: the error code
1475 * @msg: the error message
1476 * @str1: extra data
1477 * @str2: extra data
1478 *
1479 * Handle a parser error
1480 */
1481static void
1482xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1483 xmlNodePtr child, int error,
1484 const char *msg, const xmlChar * str1, const xmlChar * str2)
1485{
1486 if (child != NULL)
1487 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1488 else
1489 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1490}
1491
Daniel Veillard01fa6152004-06-29 17:04:39 +00001492
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001493/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001494 * xmlSchemaPErrExt:
1495 * @ctxt: the parsing context
1496 * @node: the context node
1497 * @error: the error code
1498 * @strData1: extra data
1499 * @strData2: extra data
1500 * @strData3: extra data
1501 * @msg: the message
1502 * @str1: extra parameter for the message display
1503 * @str2: extra parameter for the message display
1504 * @str3: extra parameter for the message display
1505 * @str4: extra parameter for the message display
1506 * @str5: extra parameter for the message display
1507 *
1508 * Handle a parser error
1509 */
1510static void
1511xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1512 const xmlChar * strData1, const xmlChar * strData2,
1513 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1514 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1515 const xmlChar * str5)
1516{
1517
1518 xmlGenericErrorFunc channel = NULL;
1519 xmlStructuredErrorFunc schannel = NULL;
1520 void *data = NULL;
1521
1522 if (ctxt != NULL) {
1523 ctxt->nberrors++;
1524 channel = ctxt->error;
1525 data = ctxt->userData;
1526 schannel = ctxt->serror;
1527 }
1528 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1529 error, XML_ERR_ERROR, NULL, 0,
1530 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001531 (const char *) strData3, 0, 0, msg, str1, str2,
1532 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001533}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001534
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001535/************************************************************************
1536 * *
1537 * Allround error functions *
1538 * *
1539 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001540
1541/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001542 * xmlSchemaVTypeErrMemory:
1543 * @node: a context node
1544 * @extra: extra informations
1545 *
1546 * Handle an out of memory condition
1547 */
1548static void
1549xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1550 const char *extra, xmlNodePtr node)
1551{
1552 if (ctxt != NULL) {
1553 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001554 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001555 }
1556 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1557 extra);
1558}
1559
1560/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001561 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001562 * @ctxt: the validation context
1563 * @node: the context node
1564 * @error: the error code
1565 * @msg: the error message
1566 * @str1: extra data
1567 * @str2: extra data
1568 * @str3: extra data
1569 *
1570 * Handle a validation error
1571 */
1572static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001573xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1574 int error, xmlNodePtr node, const char *msg,
1575 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001576{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001577 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001578 xmlGenericErrorFunc channel = NULL;
1579 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001580
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001581 if (ctxt != NULL) {
1582 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1583 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001584 int line = 0;
1585 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001586
1587 vctxt->nberrors++;
1588 vctxt->err = error;
1589 channel = vctxt->error;
1590 schannel = vctxt->serror;
1591 data = vctxt->userData;
1592 if ((node == NULL) && (vctxt->depth >= 0) &&
Daniel Veillard971771e2005-07-09 17:32:57 +00001593 (vctxt->inode != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001594 node = vctxt->inode->node;
Daniel Veillard971771e2005-07-09 17:32:57 +00001595 }
1596 if ((node == NULL) && (vctxt->parserCtxt != NULL) &&
1597 (vctxt->parserCtxt->input != NULL)) {
1598 file = vctxt->parserCtxt->input->filename;
1599 line = vctxt->parserCtxt->input->line;
1600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001601 __xmlRaiseError(schannel, channel, data, ctxt,
1602 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001603 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001604 (const char *) str1, (const char *) str2,
1605 (const char *) str3, 0, 0, msg, str1, str2, str3);
1606
1607 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1608 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1609
1610 pctxt->nberrors++;
1611 pctxt->err = error;
1612 channel = pctxt->error;
1613 schannel = pctxt->serror;
1614 data = pctxt->userData;
1615 __xmlRaiseError(schannel, channel, data, ctxt,
1616 node, XML_FROM_SCHEMASP,
1617 error, XML_ERR_ERROR, NULL, 0,
1618 (const char *) str1, (const char *) str2,
1619 (const char *) str3, 0, 0, msg, str1, str2, str3);
1620 } else {
1621 TODO
1622 }
1623 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001624}
1625
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001626static void
1627xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1628 int error, xmlNodePtr node, const char *msg,
1629 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001630{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001631 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001632}
1633
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001634static xmlChar *
1635xmlSchemaFormatNodeForError(xmlChar ** msg,
1636 xmlSchemaAbstractCtxtPtr actxt,
1637 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001638{
1639 xmlChar *str = NULL;
1640
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001641 if (node != NULL) {
1642 /*
1643 * Work on tree nodes.
1644 */
1645 if (node->type == XML_ATTRIBUTE_NODE) {
1646 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001647
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001648 *msg = xmlStrdup(BAD_CAST "Element '");
1649 if (elem->ns != NULL)
1650 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1651 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001652 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001653 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1654 NULL, elem->name));
1655 FREE_AND_NULL(str);
1656 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1657 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1658 } else {
1659 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001660 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001661 if (node->ns != NULL)
1662 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1663 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001664 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001665 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1666 NULL, node->name));
1667 FREE_AND_NULL(str);
1668 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1669 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1670 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1671 /*
1672 * Work on node infos.
1673 */
1674 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1675 xmlSchemaNodeInfoPtr ielem =
1676 vctxt->elemInfos[vctxt->depth];
1677
1678 *msg = xmlStrdup(BAD_CAST "Element '");
1679 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1680 ielem->nsName, ielem->localName));
1681 FREE_AND_NULL(str);
1682 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1683 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1684 } else {
1685 *msg = xmlStrdup(BAD_CAST "Element '");
1686 }
1687 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1688 vctxt->inode->nsName, vctxt->inode->localName));
1689 FREE_AND_NULL(str);
1690 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1691 } else {
1692 TODO
1693 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001694 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001695 /*
1696 * VAL TODO: The output of the given schema component is currently
1697 * disabled.
1698 */
1699#if 0
1700 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1701 *msg = xmlStrcat(*msg, BAD_CAST " [");
1702 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1703 NULL, type, NULL, 0));
1704 FREE_AND_NULL(str)
1705 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001706 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001707#endif
1708 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001709}
1710
Daniel Veillardc0826a72004-08-10 14:17:33 +00001711static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001712xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001713 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001714 const char *message,
1715 const xmlChar *str1,
1716 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001717{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001718 xmlChar *msg = NULL;
1719
1720 msg = xmlStrdup(BAD_CAST "Internal error: ");
1721 msg = xmlStrcat(msg, BAD_CAST funcName);
1722 msg = xmlStrcat(msg, BAD_CAST ", ");
1723 msg = xmlStrcat(msg, BAD_CAST message);
1724 msg = xmlStrcat(msg, BAD_CAST ".\n");
1725
1726 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1727 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001728 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001729
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001730 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001731 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001732 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001733
1734 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001735}
1736
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001737static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001738xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1739 const char *funcName,
1740 const char *message)
1741{
1742 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
1743}
1744
1745static void
1746xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
1747 const char *funcName,
1748 const char *message,
1749 const xmlChar *str1,
1750 const xmlChar *str2)
1751{
1752 xmlSchemaInternalErr2((xmlSchemaAbstractCtxtPtr) pctxt, funcName, message,
1753 str1, str2);
1754}
1755
1756static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001757xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1758 xmlParserErrors error,
1759 xmlNodePtr node,
1760 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1761 const char *message,
1762 const xmlChar *str1,
1763 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001764{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001765 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001766
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001767 xmlSchemaFormatNodeForError(&msg, actxt, node);
1768 msg = xmlStrcat(msg, (const xmlChar *) message);
1769 msg = xmlStrcat(msg, BAD_CAST ".\n");
1770 xmlSchemaErr(actxt, error, node,
1771 (const char *) msg, str1, str2);
1772 FREE_AND_NULL(msg)
1773}
1774
1775static int
1776xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1777 xmlNodePtr node)
1778{
1779 if (node != NULL)
1780 return (node->type);
1781 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1782 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1783 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1784 return (-1);
1785}
1786
1787static int
1788xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1789{
1790 switch (item->type) {
1791 case XML_SCHEMA_TYPE_COMPLEX:
1792 case XML_SCHEMA_TYPE_SIMPLE:
1793 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1794 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001795 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001796 case XML_SCHEMA_TYPE_GROUP:
1797 return (1);
1798 case XML_SCHEMA_TYPE_ELEMENT:
1799 if ( ((xmlSchemaElementPtr) item)->flags &
1800 XML_SCHEMAS_ELEM_GLOBAL)
1801 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001802 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001803 case XML_SCHEMA_TYPE_ATTRIBUTE:
1804 if ( ((xmlSchemaAttributePtr) item)->flags &
1805 XML_SCHEMAS_ATTR_GLOBAL)
1806 return(1);
1807 break;
1808 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001809 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001810 return(1);
1811 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001812 return (0);
1813}
1814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001815static void
1816xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1817 xmlParserErrors error,
1818 xmlNodePtr node,
1819 const xmlChar *value,
1820 xmlSchemaTypePtr type,
1821 int displayValue)
1822{
1823 xmlChar *msg = NULL;
1824
1825 xmlSchemaFormatNodeForError(&msg, actxt, node);
1826
1827 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1828 XML_ATTRIBUTE_NODE))
1829 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1830 else
1831 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1832 "value of ");
1833
1834 if (! xmlSchemaIsGlobalItem(type))
1835 msg = xmlStrcat(msg, BAD_CAST "the local ");
1836 else
1837 msg = xmlStrcat(msg, BAD_CAST "the ");
1838
1839 if (VARIETY_ATOMIC(type))
1840 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1841 else if (VARIETY_LIST(type))
1842 msg = xmlStrcat(msg, BAD_CAST "list type");
1843 else if (VARIETY_UNION(type))
1844 msg = xmlStrcat(msg, BAD_CAST "union type");
1845
1846 if (xmlSchemaIsGlobalItem(type)) {
1847 xmlChar *str = NULL;
1848 msg = xmlStrcat(msg, BAD_CAST " '");
1849 if (type->builtInType != 0) {
1850 msg = xmlStrcat(msg, BAD_CAST "xs:");
1851 msg = xmlStrcat(msg, type->name);
1852 } else
1853 msg = xmlStrcat(msg,
1854 xmlSchemaFormatQName(&str,
1855 type->targetNamespace, type->name));
1856 msg = xmlStrcat(msg, BAD_CAST "'");
1857 FREE_AND_NULL(str);
1858 }
1859 msg = xmlStrcat(msg, BAD_CAST ".\n");
1860 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1861 XML_ATTRIBUTE_NODE))
1862 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1863 else
1864 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1865 FREE_AND_NULL(msg)
1866}
1867
Daniel Veillardc0826a72004-08-10 14:17:33 +00001868static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001869xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1870 xmlSchemaNodeInfoPtr ni,
1871 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001872{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001873 if (node != NULL) {
1874 if (node->ns != NULL)
1875 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1876 else
1877 return (xmlSchemaFormatQName(str, NULL, node->name));
1878 } else if (ni != NULL)
1879 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1880 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001881}
1882
Daniel Veillardc0826a72004-08-10 14:17:33 +00001883static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001884xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1885 xmlParserErrors error,
1886 xmlSchemaAttrInfoPtr ni,
1887 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001888{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001889 xmlChar *msg = NULL, *str = NULL;
1890
1891 xmlSchemaFormatNodeForError(&msg, actxt, node);
1892 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1893 xmlSchemaErr(actxt, error, node, (const char *) msg,
1894 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1895 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001896 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001897 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001898}
1899
Daniel Veillardc0826a72004-08-10 14:17:33 +00001900static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001901xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1902 xmlParserErrors error,
1903 xmlNodePtr node,
1904 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001905 const char *message,
1906 int nbval,
1907 int nbneg,
1908 xmlChar **values)
1909{
1910 xmlChar *str = NULL, *msg = NULL;
1911 xmlChar *localName, *nsName;
1912 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00001913 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001914
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001915 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001916 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001917 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001918 /*
1919 * Note that is does not make sense to report that we have a
1920 * wildcard here, since the wildcard might be unfolded into
1921 * multiple transitions.
1922 */
1923 if (nbval + nbneg > 0) {
1924 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001925 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001926 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001927 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001928 nsName = NULL;
1929
1930 for (i = 0; i < nbval + nbneg; i++) {
1931 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00001932 if (cur == NULL)
1933 continue;
1934 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
1935 (cur[3] == ' ')) {
1936 is_not = 1;
1937 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00001938 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00001939 } else {
1940 is_not = 0;
1941 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001942 /*
1943 * Get the local name.
1944 */
1945 localName = NULL;
1946
1947 end = cur;
1948 if (*end == '*') {
1949 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001950 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001951 } else {
1952 while ((*end != 0) && (*end != '|'))
1953 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001954 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001955 }
1956 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001957 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001958 /*
1959 * Skip "*|*" if they come with negated expressions, since
1960 * they represent the same negated wildcard.
1961 */
1962 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1963 /*
1964 * Get the namespace name.
1965 */
1966 cur = end;
1967 if (*end == '*') {
1968 nsName = xmlStrdup(BAD_CAST "{*}");
1969 } else {
1970 while (*end != 0)
1971 end++;
1972
1973 if (i >= nbval)
1974 nsName = xmlStrdup(BAD_CAST "{##other:");
1975 else
1976 nsName = xmlStrdup(BAD_CAST "{");
1977
1978 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1979 nsName = xmlStrcat(nsName, BAD_CAST "}");
1980 }
1981 str = xmlStrcat(str, BAD_CAST nsName);
1982 FREE_AND_NULL(nsName)
1983 } else {
1984 FREE_AND_NULL(localName);
1985 continue;
1986 }
1987 }
1988 str = xmlStrcat(str, BAD_CAST localName);
1989 FREE_AND_NULL(localName);
1990
1991 if (i < nbval + nbneg -1)
1992 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001993 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001994 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001995 msg = xmlStrcat(msg, BAD_CAST str);
1996 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001997 } else
1998 msg = xmlStrcat(msg, BAD_CAST "\n");
1999 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002000 xmlFree(msg);
2001}
2002
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002003static void
2004xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2005 xmlParserErrors error,
2006 xmlNodePtr node,
2007 const xmlChar *value,
2008 unsigned long length,
2009 xmlSchemaTypePtr type,
2010 xmlSchemaFacetPtr facet,
2011 const char *message,
2012 const xmlChar *str1,
2013 const xmlChar *str2)
2014{
2015 xmlChar *str = NULL, *msg = NULL;
2016 xmlSchemaTypeType facetType;
2017 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2018
2019 xmlSchemaFormatNodeForError(&msg, actxt, node);
2020 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2021 facetType = XML_SCHEMA_FACET_ENUMERATION;
2022 /*
2023 * If enumerations are validated, one must not expect the
2024 * facet to be given.
2025 */
2026 } else
2027 facetType = facet->type;
2028 msg = xmlStrcat(msg, BAD_CAST "[");
2029 msg = xmlStrcat(msg, BAD_CAST "facet '");
2030 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2031 msg = xmlStrcat(msg, BAD_CAST "'] ");
2032 if (message == NULL) {
2033 /*
2034 * Use a default message.
2035 */
2036 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2037 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2038 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2039
2040 char len[25], actLen[25];
2041
2042 /* FIXME, TODO: What is the max expected string length of the
2043 * this value?
2044 */
2045 if (nodeType == XML_ATTRIBUTE_NODE)
2046 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2047 else
2048 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2049
2050 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2051 snprintf(actLen, 24, "%lu", length);
2052
2053 if (facetType == XML_SCHEMA_FACET_LENGTH)
2054 msg = xmlStrcat(msg,
2055 BAD_CAST "this differs from the allowed length of '%s'.\n");
2056 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2057 msg = xmlStrcat(msg,
2058 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2059 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2060 msg = xmlStrcat(msg,
2061 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2062
2063 if (nodeType == XML_ATTRIBUTE_NODE)
2064 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2065 value, (const xmlChar *) actLen, (const xmlChar *) len);
2066 else
2067 xmlSchemaErr(actxt, error, node, (const char *) msg,
2068 (const xmlChar *) actLen, (const xmlChar *) len);
2069
2070 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2071 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2072 "of the set {%s}.\n");
2073 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2074 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2075 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2076 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2077 "by the pattern '%s'.\n");
2078 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2079 facet->value);
2080 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2081 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2082 "minimum value allowed ('%s').\n");
2083 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2084 facet->value);
2085 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2086 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2087 "maximum value allowed ('%s').\n");
2088 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2089 facet->value);
2090 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2091 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2092 "'%s'.\n");
2093 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2094 facet->value);
2095 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2096 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2097 "'%s'.\n");
2098 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2099 facet->value);
2100 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2101 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2102 "digits than are allowed ('%s').\n");
2103 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2104 facet->value);
2105 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2106 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2107 "digits than are allowed ('%s').\n");
2108 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2109 facet->value);
2110 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2111 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2112 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2113 } else {
2114 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2115 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2116 }
2117 } else {
2118 msg = xmlStrcat(msg, (const xmlChar *) message);
2119 msg = xmlStrcat(msg, BAD_CAST ".\n");
2120 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2121 }
2122 FREE_AND_NULL(str)
2123 xmlFree(msg);
2124}
2125
2126#define VERROR(err, type, msg) \
2127 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2128
2129#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2130
2131#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2132
2133#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2134
2135
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002136/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002137 * xmlSchemaPMissingAttrErr:
2138 * @ctxt: the schema validation context
2139 * @ownerDes: the designation of the owner
2140 * @ownerName: the name of the owner
2141 * @ownerItem: the owner as a schema object
2142 * @ownerElem: the owner as an element node
2143 * @node: the parent element node of the missing attribute node
2144 * @type: the corresponding type of the attribute node
2145 *
2146 * Reports an illegal attribute.
2147 */
2148static void
2149xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002150 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002151 xmlSchemaTypePtr ownerItem,
2152 xmlNodePtr ownerElem,
2153 const char *name,
2154 const char *message)
2155{
2156 xmlChar *des = NULL;
2157
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002158 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2159
Daniel Veillardc0826a72004-08-10 14:17:33 +00002160 if (message != NULL)
2161 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 else
2163 xmlSchemaPErr(ctxt, ownerElem, error,
2164 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002165 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002166 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002167}
2168
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002169
Daniel Veillardc0826a72004-08-10 14:17:33 +00002170/**
2171 * xmlSchemaPResCompAttrErr:
2172 * @ctxt: the schema validation context
2173 * @error: the error code
2174 * @ownerDes: the designation of the owner
2175 * @ownerItem: the owner as a schema object
2176 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002177 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002178 * @refName: the referenced local name
2179 * @refURI: the referenced namespace URI
2180 * @message: optional message
2181 *
2182 * Used to report QName attribute values that failed to resolve
2183 * to schema components.
2184 */
2185static void
2186xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002187 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002188 xmlSchemaTypePtr ownerItem,
2189 xmlNodePtr ownerElem,
2190 const char *name,
2191 const xmlChar *refName,
2192 const xmlChar *refURI,
2193 xmlSchemaTypeType refType,
2194 const char *refTypeStr)
2195{
2196 xmlChar *des = NULL, *strA = NULL;
2197
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002198 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002199 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002200 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2201 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002202 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002203 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2204 "%s.\n", BAD_CAST des, BAD_CAST name,
2205 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002206 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002207 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002208 FREE_AND_NULL(strA)
2209}
2210
William M. Brack2f2a6632004-08-20 23:09:47 +00002211/**
2212 * xmlSchemaPCustomAttrErr:
2213 * @ctxt: the schema parser context
2214 * @error: the error code
2215 * @ownerDes: the designation of the owner
2216 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002217 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002218 *
2219 * Reports an illegal attribute during the parse.
2220 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221static void
2222xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002223 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002224 xmlChar **ownerDes,
2225 xmlSchemaTypePtr ownerItem,
2226 xmlAttrPtr attr,
2227 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002228{
2229 xmlChar *des = NULL;
2230
2231 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002232 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002233 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002234 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002235 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002236 } else
2237 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002238 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002239 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002240 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2241 if (ownerDes == NULL)
2242 FREE_AND_NULL(des);
2243}
2244
2245/**
2246 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002247 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002248 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002249 * @ownerDes: the designation of the attribute's owner
2250 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002251 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002252 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002253 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002254 */
2255static void
2256xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002257 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002258 xmlChar **ownerDes,
2259 xmlSchemaTypePtr ownerItem,
2260 xmlAttrPtr attr)
2261{
2262 xmlChar *des = NULL, *strA = NULL;
2263
2264 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002265 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002266 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002267 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002268 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002269 } else
2270 des = *ownerDes;
2271 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2272 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2273 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002274 if (ownerDes == NULL)
2275 FREE_AND_NULL(des);
2276 FREE_AND_NULL(strA);
2277}
2278
William M. Brack2f2a6632004-08-20 23:09:47 +00002279/**
2280 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002281 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002282 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002283 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002284 * @itemElem: the node of the schema item
2285 *
2286 * Creates a designation for an item.
2287 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002288static void
2289xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002290 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002291 xmlSchemaTypePtr item,
2292 xmlNodePtr itemElem)
2293{
2294 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002295 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002296 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002297 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002298 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002299 } else
2300 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002301}
2302
William M. Brack2f2a6632004-08-20 23:09:47 +00002303/**
2304 * xmlSchemaPCustomErr:
2305 * @ctxt: the schema parser context
2306 * @error: the error code
2307 * @itemDes: the designation of the schema item
2308 * @item: the schema item
2309 * @itemElem: the node of the schema item
2310 * @message: the error message
2311 * @str1: an optional param for the error message
2312 * @str2: an optional param for the error message
2313 * @str3: an optional param for the error message
2314 *
2315 * Reports an error during parsing.
2316 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002317static void
2318xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002319 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002320 xmlChar **itemDes,
2321 xmlSchemaTypePtr item,
2322 xmlNodePtr itemElem,
2323 const char *message,
2324 const xmlChar *str1,
2325 const xmlChar *str2,
2326 const xmlChar *str3)
2327{
2328 xmlChar *des = NULL, *msg = NULL;
2329
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002330 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002331 msg = xmlStrdup(BAD_CAST "%s: ");
2332 msg = xmlStrcat(msg, (const xmlChar *) message);
2333 msg = xmlStrcat(msg, BAD_CAST ".\n");
2334 if ((itemElem == NULL) && (item != NULL))
2335 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002336 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002337 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2338 if (itemDes == NULL)
2339 FREE_AND_NULL(des);
2340 FREE_AND_NULL(msg);
2341}
2342
William M. Brack2f2a6632004-08-20 23:09:47 +00002343/**
2344 * xmlSchemaPCustomErr:
2345 * @ctxt: the schema parser context
2346 * @error: the error code
2347 * @itemDes: the designation of the schema item
2348 * @item: the schema item
2349 * @itemElem: the node of the schema item
2350 * @message: the error message
2351 * @str1: the optional param for the error message
2352 *
2353 * Reports an error during parsing.
2354 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002355static void
2356xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002357 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002358 xmlChar **itemDes,
2359 xmlSchemaTypePtr item,
2360 xmlNodePtr itemElem,
2361 const char *message,
2362 const xmlChar *str1)
2363{
2364 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2365 str1, NULL, NULL);
2366}
2367
William M. Brack2f2a6632004-08-20 23:09:47 +00002368/**
2369 * xmlSchemaPAttrUseErr:
2370 * @ctxt: the schema parser context
2371 * @error: the error code
2372 * @itemDes: the designation of the schema type
2373 * @item: the schema type
2374 * @itemElem: the node of the schema type
2375 * @attr: the invalid schema attribute
2376 * @message: the error message
2377 * @str1: the optional param for the error message
2378 *
2379 * Reports an attribute use error during parsing.
2380 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002381static void
2382xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002383 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002384 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002385 const xmlSchemaAttributePtr attr,
2386 const char *message,
2387 const xmlChar *str1)
2388{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002389 xmlChar *str = NULL, *msg = NULL;
2390 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2391 msg = xmlStrcat(msg, BAD_CAST ", ");
2392 msg = xmlStrcat(msg,
2393 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2394 (xmlSchemaTypePtr) attr, NULL));
2395 FREE_AND_NULL(str);
2396 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002397 msg = xmlStrcat(msg, (const xmlChar *) message);
2398 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002399 xmlSchemaPErr(ctxt, attr->node, error,
2400 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002401 xmlFree(msg);
2402}
2403
William M. Brack2f2a6632004-08-20 23:09:47 +00002404/**
2405 * xmlSchemaPIllegalFacetAtomicErr:
2406 * @ctxt: the schema parser context
2407 * @error: the error code
2408 * @itemDes: the designation of the type
2409 * @item: the schema type
2410 * @baseItem: the base type of type
2411 * @facet: the illegal facet
2412 *
2413 * Reports an illegal facet for atomic simple types.
2414 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002415static void
2416xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002417 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002418 xmlChar **itemDes,
2419 xmlSchemaTypePtr item,
2420 xmlSchemaTypePtr baseItem,
2421 xmlSchemaFacetPtr facet)
2422{
2423 xmlChar *des = NULL, *strT = NULL;
2424
2425 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2426 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2427 "%s: The facet '%s' is not allowed on types derived from the "
2428 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002429 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002430 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002431 NULL, NULL);
2432 if (itemDes == NULL)
2433 FREE_AND_NULL(des);
2434 FREE_AND_NULL(strT);
2435}
2436
William M. Brack2f2a6632004-08-20 23:09:47 +00002437/**
2438 * xmlSchemaPIllegalFacetListUnionErr:
2439 * @ctxt: the schema parser context
2440 * @error: the error code
2441 * @itemDes: the designation of the schema item involved
2442 * @item: the schema item involved
2443 * @facet: the illegal facet
2444 *
2445 * Reports an illegal facet for <list> and <union>.
2446 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002447static void
2448xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002449 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002450 xmlChar **itemDes,
2451 xmlSchemaTypePtr item,
2452 xmlSchemaFacetPtr facet)
2453{
2454 xmlChar *des = NULL, *strT = NULL;
2455
2456 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002457 xmlSchemaPErr(ctxt, item->node, error,
2458 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002459 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002460 if (itemDes == NULL)
2461 FREE_AND_NULL(des);
2462 FREE_AND_NULL(strT);
2463}
2464
2465/**
2466 * xmlSchemaPMutualExclAttrErr:
2467 * @ctxt: the schema validation context
2468 * @error: the error code
2469 * @elemDes: the designation of the parent element node
2470 * @attr: the bad attribute node
2471 * @type: the corresponding type of the attribute node
2472 *
2473 * Reports an illegal attribute.
2474 */
2475static void
2476xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2477 xmlParserErrors error,
2478 xmlChar **ownerDes,
2479 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002480 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002481 const char *name1,
2482 const char *name2)
2483{
2484 xmlChar *des = NULL;
2485
2486 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002487 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002488 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002489 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002490 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002491 } else
2492 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002493 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002494 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002495 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2496 if (ownerDes == NULL)
2497 FREE_AND_NULL(des)
2498}
2499
2500/**
2501 * xmlSchemaPSimpleTypeErr:
2502 * @ctxt: the schema validation context
2503 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002504 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002505 * @ownerDes: the designation of the owner
2506 * @ownerItem: the schema object if existent
2507 * @node: the validated node
2508 * @value: the validated value
2509 *
2510 * Reports a simple type validation error.
2511 * TODO: Should this report the value of an element as well?
2512 */
2513static void
2514xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2515 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002516 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002517 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002518 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002519 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002520 const xmlChar *value,
2521 const char *message,
2522 const xmlChar *str1,
2523 const xmlChar *str2)
2524{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002525 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002526
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002527 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002528 if (message == NULL) {
2529 /*
2530 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002531 */
2532 if (type != NULL) {
2533 if (node->type == XML_ATTRIBUTE_NODE)
2534 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2535 else
2536 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2537 "valid value of ");
2538 if (! xmlSchemaIsGlobalItem(type))
2539 msg = xmlStrcat(msg, BAD_CAST "the local ");
2540 else
2541 msg = xmlStrcat(msg, BAD_CAST "the ");
2542
2543 if (VARIETY_ATOMIC(type))
2544 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2545 else if (VARIETY_LIST(type))
2546 msg = xmlStrcat(msg, BAD_CAST "list type");
2547 else if (VARIETY_UNION(type))
2548 msg = xmlStrcat(msg, BAD_CAST "union type");
2549
2550 if (xmlSchemaIsGlobalItem(type)) {
2551 xmlChar *str = NULL;
2552 msg = xmlStrcat(msg, BAD_CAST " '");
2553 if (type->builtInType != 0) {
2554 msg = xmlStrcat(msg, BAD_CAST "xs:");
2555 msg = xmlStrcat(msg, type->name);
2556 } else
2557 msg = xmlStrcat(msg,
2558 xmlSchemaFormatQName(&str,
2559 type->targetNamespace, type->name));
2560 msg = xmlStrcat(msg, BAD_CAST "'.");
2561 FREE_AND_NULL(str);
2562 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002563 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002564 if (node->type == XML_ATTRIBUTE_NODE)
2565 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2566 else
2567 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2568 "valid.");
2569 }
2570 if (expected) {
2571 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2572 msg = xmlStrcat(msg, BAD_CAST expected);
2573 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2574 } else
2575 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002576 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002577 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2578 else
2579 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2580 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002581 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00002582 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002583 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002584 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002585 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002586 /* Cleanup. */
2587 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002588}
2589
William M. Brack2f2a6632004-08-20 23:09:47 +00002590/**
2591 * xmlSchemaPContentErr:
2592 * @ctxt: the schema parser context
2593 * @error: the error code
2594 * @onwerDes: the designation of the holder of the content
2595 * @ownerItem: the owner item of the holder of the content
2596 * @ownerElem: the node of the holder of the content
2597 * @child: the invalid child node
2598 * @message: the optional error message
2599 * @content: the optional string describing the correct content
2600 *
2601 * Reports an error concerning the content of a schema element.
2602 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002603static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002604xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002605 xmlParserErrors error,
2606 xmlChar **ownerDes,
2607 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002608 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002609 xmlNodePtr child,
2610 const char *message,
2611 const char *content)
2612{
2613 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002614
Daniel Veillardc0826a72004-08-10 14:17:33 +00002615 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002616 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002617 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002618 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002619 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002620 } else
2621 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002622 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002623 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2624 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002625 BAD_CAST des, BAD_CAST message);
2626 else {
2627 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002628 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2629 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002630 BAD_CAST des, BAD_CAST content);
2631 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002632 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2633 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002634 BAD_CAST des, NULL);
2635 }
2636 }
2637 if (ownerDes == NULL)
2638 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002639}
2640
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002641/************************************************************************
2642 * *
2643 * Streamable error functions *
2644 * *
2645 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002646
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002647
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002648
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002649
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002650/************************************************************************
2651 * *
2652 * Validation helper functions *
2653 * *
2654 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002655
Daniel Veillardc0826a72004-08-10 14:17:33 +00002656
Daniel Veillard4255d502002-04-16 15:50:10 +00002657/************************************************************************
2658 * *
2659 * Allocation functions *
2660 * *
2661 ************************************************************************/
2662
2663/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002664 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002665 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002666 *
2667 * Allocate a new Schema structure.
2668 *
2669 * Returns the newly allocated structure or NULL in case or error
2670 */
2671static xmlSchemaPtr
2672xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2673{
2674 xmlSchemaPtr ret;
2675
2676 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2677 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002678 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002679 return (NULL);
2680 }
2681 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002682 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002683 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002684
2685 return (ret);
2686}
2687
2688/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002689 * xmlSchemaNewSchema:
2690 * @ctxt: a schema validation context
2691 *
2692 * Allocate a new Schema structure.
2693 *
2694 * Returns the newly allocated structure or NULL in case or error
2695 */
2696static xmlSchemaAssemblePtr
2697xmlSchemaNewAssemble(void)
2698{
2699 xmlSchemaAssemblePtr ret;
2700
2701 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2702 if (ret == NULL) {
2703 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2704 return (NULL);
2705 }
2706 memset(ret, 0, sizeof(xmlSchemaAssemble));
2707 ret->items = NULL;
2708 return (ret);
2709}
2710
2711/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002712 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002713 *
2714 * Allocate a new Facet structure.
2715 *
2716 * Returns the newly allocated structure or NULL in case or error
2717 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002718xmlSchemaFacetPtr
2719xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002720{
2721 xmlSchemaFacetPtr ret;
2722
2723 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2724 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002725 return (NULL);
2726 }
2727 memset(ret, 0, sizeof(xmlSchemaFacet));
2728
2729 return (ret);
2730}
2731
2732/**
2733 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002734 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002735 * @node: a node
2736 *
2737 * Allocate a new annotation structure.
2738 *
2739 * Returns the newly allocated structure or NULL in case or error
2740 */
2741static xmlSchemaAnnotPtr
2742xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2743{
2744 xmlSchemaAnnotPtr ret;
2745
2746 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2747 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002748 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002749 return (NULL);
2750 }
2751 memset(ret, 0, sizeof(xmlSchemaAnnot));
2752 ret->content = node;
2753 return (ret);
2754}
2755
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002756static xmlSchemaItemListPtr
2757xmlSchemaNewItemList(void)
2758{
2759 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002760
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002761 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2762 if (ret == NULL) {
2763 xmlSchemaPErrMemory(NULL,
2764 "allocating an item list structure", NULL);
2765 return (NULL);
2766 }
2767 memset(ret, 0, sizeof(xmlSchemaItemList));
2768 return (ret);
2769}
2770
2771/**
2772 * xmlSchemaAddElementSubstitutionMember:
2773 * @pctxt: a schema parser context
2774 * @head: the head of the substitution group
2775 * @member: the new member of the substitution group
2776 *
2777 * Allocate a new annotation structure.
2778 *
2779 * Returns the newly allocated structure or NULL in case or error
2780 */
2781static int
2782xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2783 xmlSchemaElementPtr head,
2784 xmlSchemaElementPtr member)
2785{
2786 xmlSchemaSubstGroupPtr substGroup;
2787
2788 if (pctxt == NULL)
2789 return (-1);
2790
2791 if (pctxt->substGroups == NULL) {
2792 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2793 if (pctxt->substGroups == NULL)
2794 return (-1);
2795 }
2796 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2797 head->targetNamespace);
2798 if (substGroup == NULL) {
2799 int res;
2800
2801 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2802 if (substGroup == NULL) {
2803 xmlSchemaPErrMemory(NULL,
2804 "xmlSchemaAddElementSubstitution, allocating a substitution "
2805 "group container",
2806 NULL);
2807 return (-1);
2808 }
2809 substGroup->members = xmlSchemaNewItemList();
2810 if (substGroup->members == NULL) {
2811 xmlFree(substGroup);
2812 return (-1);
2813 }
2814 substGroup->head = head;
2815
2816 res = xmlHashAddEntry2(pctxt->substGroups,
2817 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002818 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002819 xmlFree(substGroup->members);
2820 xmlFree(substGroup);
2821 xmlSchemaPErr(pctxt, member->node,
2822 XML_SCHEMAP_INTERNAL,
2823 "Internal error: xmlSchemaAddElementSubstitution, "
2824 "failed to add a new substitution group container for "
2825 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002826 return (-1);
2827 }
2828 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002829 if (substGroup->members->items == NULL) {
2830 substGroup->members->items = (void **) xmlMalloc(
2831 5 * sizeof(xmlSchemaElementPtr));
2832 if (substGroup->members->items == NULL) {
2833 xmlSchemaPErrMemory(NULL,
2834 "allocating list of substitution group members", NULL);
2835 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002836 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002837 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002838 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002839 substGroup->members->nbItems) {
2840 substGroup->members->sizeItems *= 2;
2841 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002842 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002843 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2844 if (substGroup->members->items == NULL) {
2845 xmlSchemaPErrMemory(NULL,
2846 "re-allocating list of substitution group members", NULL);
2847 substGroup->members->sizeItems = 0;
2848 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002849 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002850 }
2851 ((xmlSchemaElementPtr *) substGroup->members->items)
2852 [substGroup->members->nbItems++] = (void *) member;
2853 return (0);
2854}
2855
2856/**
2857 * xmlSchemaGetElementSubstitutionGroup:
2858 * @pctxt: a schema parser context
2859 * @head: the head of the substitution group
2860 * @member: the new member of the substitution group
2861 *
2862 * Allocate a new annotation structure.
2863 *
2864 * Returns the newly allocated structure or NULL in case or error
2865 */
2866static xmlSchemaSubstGroupPtr
2867xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2868 xmlSchemaElementPtr head)
2869{
2870 if (pctxt == NULL)
2871 return (NULL);
2872
2873 if (pctxt->substGroups == NULL)
2874 return (NULL);
2875
2876 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2877 head->name, head->targetNamespace));
2878}
2879
2880/**
2881 * xmlSchemaFreeItemList:
2882 * @annot: a schema type structure
2883 *
2884 * Deallocate a annotation structure
2885 */
2886static void
2887xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2888{
2889 if (list == NULL)
2890 return;
2891 if (list->items != NULL)
2892 xmlFree(list->items);
2893 xmlFree(list);
2894}
2895
Daniel Veillard4255d502002-04-16 15:50:10 +00002896/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002897 * xmlSchemaFreeAnnot:
2898 * @annot: a schema type structure
2899 *
2900 * Deallocate a annotation structure
2901 */
2902static void
2903xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2904{
2905 if (annot == NULL)
2906 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00002907 if (annot->next == NULL) {
2908 xmlFree(annot);
2909 } else {
2910 xmlSchemaAnnotPtr prev;
2911
2912 do {
2913 prev = annot;
2914 annot = annot->next;
2915 xmlFree(prev);
2916 } while (annot != NULL);
2917 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00002918}
2919
2920/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002921 * xmlSchemaFreeImport:
2922 * @import: a schema import structure
2923 *
2924 * Deallocate an import structure
2925 */
2926static void
2927xmlSchemaFreeImport(xmlSchemaImportPtr import)
2928{
2929 if (import == NULL)
2930 return;
2931
2932 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002933 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002934 xmlFree(import);
2935}
2936
2937/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002938 * xmlSchemaFreeInclude:
2939 * @include: a schema include structure
2940 *
2941 * Deallocate an include structure
2942 */
2943static void
2944xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2945{
2946 if (include == NULL)
2947 return;
2948
2949 xmlFreeDoc(include->doc);
2950 xmlFree(include);
2951}
2952
2953/**
2954 * xmlSchemaFreeIncludeList:
2955 * @includes: a schema include list
2956 *
2957 * Deallocate an include structure
2958 */
2959static void
2960xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2961{
2962 xmlSchemaIncludePtr next;
2963
2964 while (includes != NULL) {
2965 next = includes->next;
2966 xmlSchemaFreeInclude(includes);
2967 includes = next;
2968 }
2969}
2970
2971/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002972 * xmlSchemaFreeNotation:
2973 * @schema: a schema notation structure
2974 *
2975 * Deallocate a Schema Notation structure.
2976 */
2977static void
2978xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2979{
2980 if (nota == NULL)
2981 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002982 xmlFree(nota);
2983}
2984
2985/**
2986 * xmlSchemaFreeAttribute:
2987 * @schema: a schema attribute structure
2988 *
2989 * Deallocate a Schema Attribute structure.
2990 */
2991static void
2992xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2993{
2994 if (attr == NULL)
2995 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002996 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002997 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002998 if (attr->defVal != NULL)
2999 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003000 xmlFree(attr);
3001}
3002
3003/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003004 * xmlSchemaFreeWildcardNsSet:
3005 * set: a schema wildcard namespace
3006 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003007 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003008 */
3009static void
3010xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3011{
3012 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003013
Daniel Veillard3646d642004-06-02 19:19:14 +00003014 while (set != NULL) {
3015 next = set->next;
3016 xmlFree(set);
3017 set = next;
3018 }
3019}
3020
3021/**
3022 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003023 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003024 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003025 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003026 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003027void
Daniel Veillard3646d642004-06-02 19:19:14 +00003028xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3029{
3030 if (wildcard == NULL)
3031 return;
3032 if (wildcard->annot != NULL)
3033 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003034 if (wildcard->nsSet != NULL)
3035 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3036 if (wildcard->negNsSet != NULL)
3037 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003038 xmlFree(wildcard);
3039}
3040
3041/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003042 * xmlSchemaFreeAttributeGroup:
3043 * @schema: a schema attribute group structure
3044 *
3045 * Deallocate a Schema Attribute Group structure.
3046 */
3047static void
3048xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3049{
3050 if (attr == NULL)
3051 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003052 if (attr->annot != NULL)
3053 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003054 xmlFree(attr);
3055}
3056
3057/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003058 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003059 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003060 *
3061 * Deallocate a list of schema attribute uses.
3062 */
3063static void
3064xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3065{
3066 xmlSchemaAttributeLinkPtr next;
3067
3068 while (attrUse != NULL) {
3069 next = attrUse->next;
3070 xmlFree(attrUse);
3071 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003072 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003073}
3074
3075/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003076 * xmlSchemaFreeQNameRef:
3077 * @item: a QName reference structure
3078 *
3079 * Deallocatea a QName reference structure.
3080 */
3081static void
3082xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3083{
3084 xmlFree(item);
3085}
3086
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003087/**
3088 * xmlSchemaFreeQNameRef:
3089 * @item: a QName reference structure
3090 *
3091 * Deallocatea a QName reference structure.
3092 */
3093static void
3094xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3095{
3096 if (item == NULL)
3097 return;
3098 if (item->members != NULL)
3099 xmlSchemaFreeItemList(item->members);
3100 xmlFree(item);
3101}
3102
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003103static int
3104xmlSchemaAddVolatile(xmlSchemaPtr schema,
3105 xmlSchemaBasicItemPtr item)
3106{
3107 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003108
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003109 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003110 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003111 if (schema->volatiles == NULL) {
3112 xmlSchemaPErrMemory(NULL,
3113 "allocating list of volatiles", NULL);
3114 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003115 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003116 }
3117 list = (xmlSchemaItemListPtr) schema->volatiles;
3118 if (list->items == NULL) {
3119 list->items = (void **) xmlMalloc(
3120 20 * sizeof(xmlSchemaBasicItemPtr));
3121 if (list->items == NULL) {
3122 xmlSchemaPErrMemory(NULL,
3123 "allocating new volatile item buffer", NULL);
3124 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003125 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003126 list->sizeItems = 20;
3127 } else if (list->sizeItems <= list->nbItems) {
3128 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003129 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003130 list->sizeItems * sizeof(xmlSchemaTypePtr));
3131 if (list->items == NULL) {
3132 xmlSchemaPErrMemory(NULL,
3133 "growing volatile item buffer", NULL);
3134 list->sizeItems = 0;
3135 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003136 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003137 }
3138 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3139 return (0);
3140}
3141
3142/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003143 * xmlSchemaFreeTypeLinkList:
3144 * @alink: a type link
3145 *
3146 * Deallocate a list of types.
3147 */
3148static void
3149xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3150{
3151 xmlSchemaTypeLinkPtr next;
3152
3153 while (link != NULL) {
3154 next = link->next;
3155 xmlFree(link);
3156 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003157 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003158}
3159
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003160static void
3161xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3162{
3163 xmlSchemaIDCStateObjPtr next;
3164 while (sto != NULL) {
3165 next = sto->next;
3166 if (sto->history != NULL)
3167 xmlFree(sto->history);
3168 if (sto->xpathCtxt != NULL)
3169 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3170 xmlFree(sto);
3171 sto = next;
3172 }
3173}
3174
3175/**
3176 * xmlSchemaFreeIDC:
3177 * @idc: a identity-constraint definition
3178 *
3179 * Deallocates an identity-constraint definition.
3180 */
3181static void
3182xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3183{
3184 xmlSchemaIDCSelectPtr cur, prev;
3185
3186 if (idcDef == NULL)
3187 return;
3188 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003189 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003190 /* Selector */
3191 if (idcDef->selector != NULL) {
3192 if (idcDef->selector->xpathComp != NULL)
3193 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3194 xmlFree(idcDef->selector);
3195 }
3196 /* Fields */
3197 if (idcDef->fields != NULL) {
3198 cur = idcDef->fields;
3199 do {
3200 prev = cur;
3201 cur = cur->next;
3202 if (prev->xpathComp != NULL)
3203 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003204 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003205 } while (cur != NULL);
3206 }
3207 xmlFree(idcDef);
3208}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003209
Daniel Veillard01fa6152004-06-29 17:04:39 +00003210/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003211 * xmlSchemaFreeElement:
3212 * @schema: a schema element structure
3213 *
3214 * Deallocate a Schema Element structure.
3215 */
3216static void
3217xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3218{
3219 if (elem == NULL)
3220 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003221 if (elem->annot != NULL)
3222 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003223 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003224 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003225 if (elem->defVal != NULL)
3226 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003227 xmlFree(elem);
3228}
3229
3230/**
3231 * xmlSchemaFreeFacet:
3232 * @facet: a schema facet structure
3233 *
3234 * Deallocate a Schema Facet structure.
3235 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003236void
Daniel Veillard4255d502002-04-16 15:50:10 +00003237xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3238{
3239 if (facet == NULL)
3240 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003241 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003242 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003243 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003244 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003245 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003246 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003247 xmlFree(facet);
3248}
3249
3250/**
3251 * xmlSchemaFreeType:
3252 * @type: a schema type structure
3253 *
3254 * Deallocate a Schema Type structure.
3255 */
3256void
3257xmlSchemaFreeType(xmlSchemaTypePtr type)
3258{
3259 if (type == NULL)
3260 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003261 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003262 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003263 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003264 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003265
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003266 facet = type->facets;
3267 while (facet != NULL) {
3268 next = facet->next;
3269 xmlSchemaFreeFacet(facet);
3270 facet = next;
3271 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003272 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003273 if (type->type != XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003274 /*
3275 * TODO: Why is this restricted to non built-in types?
3276 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003277 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003278 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003279 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003280 if (type->memberTypes != NULL)
3281 xmlSchemaFreeTypeLinkList(type->memberTypes);
3282 if (type->facetSet != NULL) {
3283 xmlSchemaFacetLinkPtr next, link;
3284
3285 link = type->facetSet;
3286 do {
3287 next = link->next;
3288 xmlFree(link);
3289 link = next;
3290 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003291 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003292 if (type->contModel != NULL)
3293 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003294 xmlFree(type);
3295}
3296
3297/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003298 * xmlSchemaFreeModelGroupDef:
3299 * @item: a schema model group definition
3300 *
3301 * Deallocates a schema model group definition.
3302 */
3303static void
3304xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3305{
3306 if (item->annot != NULL)
3307 xmlSchemaFreeAnnot(item->annot);
3308 xmlFree(item);
3309}
3310
3311/**
3312 * xmlSchemaFreeModelGroup:
3313 * @item: a schema model group
3314 *
3315 * Deallocates a schema model group structure.
3316 */
3317static void
3318xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3319{
3320 if (item->annot != NULL)
3321 xmlSchemaFreeAnnot(item->annot);
3322 xmlFree(item);
3323}
3324
3325/**
3326 * xmlSchemaFreeParticle:
3327 * @type: a schema type structure
3328 *
3329 * Deallocate a Schema Type structure.
3330 */
3331static void
3332xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3333{
3334 if (item->annot != NULL)
3335 xmlSchemaFreeAnnot(item->annot);
3336 xmlFree(item);
3337}
3338
3339/**
3340 * xmlSchemaFreeMiscComponents:
3341 * @item: a schema component
3342 *
3343 * Deallocates misc. schema component structures.
3344 */
3345static void
3346xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3347{
3348 if (item == NULL)
3349 return;
3350 switch (item->type) {
3351 case XML_SCHEMA_TYPE_PARTICLE:
3352 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3353 return;
3354 case XML_SCHEMA_TYPE_SEQUENCE:
3355 case XML_SCHEMA_TYPE_CHOICE:
3356 case XML_SCHEMA_TYPE_ALL:
3357 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3358 return;
3359 case XML_SCHEMA_TYPE_ANY:
3360 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3361 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3362 break;
3363 default:
3364 /* TODO: This should never be hit. */
3365 TODO
3366 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003367 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003368}
3369
3370static void
3371xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3372{
3373 if (schema->volatiles == NULL)
3374 return;
3375 {
3376 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3377 xmlSchemaTreeItemPtr item;
3378 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003379
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003380 for (i = 0; i < list->nbItems; i++) {
3381 if (list->items[i] != NULL) {
3382 item = (xmlSchemaTreeItemPtr) list->items[i];
3383 switch (item->type) {
3384 case XML_SCHEMA_EXTRA_QNAMEREF:
3385 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3386 break;
3387 default:
3388 xmlSchemaFreeMiscComponents(item);
3389 }
3390 }
3391 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003392 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003393 }
3394}
3395/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003396 * xmlSchemaFreeTypeList:
3397 * @type: a schema type structure
3398 *
3399 * Deallocate a Schema Type structure.
3400 */
3401static void
3402xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3403{
3404 xmlSchemaTypePtr next;
3405
3406 while (type != NULL) {
3407 next = type->redef;
3408 xmlSchemaFreeType(type);
3409 type = next;
3410 }
3411}
3412
3413/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003414 * xmlSchemaFree:
3415 * @schema: a schema structure
3416 *
3417 * Deallocate a Schema structure.
3418 */
3419void
3420xmlSchemaFree(xmlSchemaPtr schema)
3421{
3422 if (schema == NULL)
3423 return;
3424
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003425 if (schema->volatiles != NULL)
3426 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003427 if (schema->notaDecl != NULL)
3428 xmlHashFree(schema->notaDecl,
3429 (xmlHashDeallocator) xmlSchemaFreeNotation);
3430 if (schema->attrDecl != NULL)
3431 xmlHashFree(schema->attrDecl,
3432 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3433 if (schema->attrgrpDecl != NULL)
3434 xmlHashFree(schema->attrgrpDecl,
3435 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3436 if (schema->elemDecl != NULL)
3437 xmlHashFree(schema->elemDecl,
3438 (xmlHashDeallocator) xmlSchemaFreeElement);
3439 if (schema->typeDecl != NULL)
3440 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003441 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003442 if (schema->groupDecl != NULL)
3443 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003444 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003445 if (schema->idcDef != NULL)
3446 xmlHashFree(schema->idcDef,
3447 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003448 if (schema->schemasImports != NULL)
3449 xmlHashFree(schema->schemasImports,
3450 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003451 if (schema->includes != NULL) {
3452 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3453 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003454 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003455 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003456 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003457 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003458 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003459 xmlFree(schema);
3460}
3461
3462/************************************************************************
3463 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003464 * Debug functions *
3465 * *
3466 ************************************************************************/
3467
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003468#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003469
Daniel Veillard4255d502002-04-16 15:50:10 +00003470/**
3471 * xmlSchemaElementDump:
3472 * @elem: an element
3473 * @output: the file output
3474 *
3475 * Dump the element
3476 */
3477static void
3478xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003479 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003480 const xmlChar * namespace ATTRIBUTE_UNUSED,
3481 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003482{
3483 if (elem == NULL)
3484 return;
3485
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003486 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3487 fprintf(output, "Particle: %s", name);
3488 fprintf(output, ", term element: %s", elem->ref);
3489 if (elem->refNs != NULL)
3490 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003491 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003492 fprintf(output, "Element");
3493 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3494 fprintf(output, " (global)");
3495 fprintf(output, ": %s ", elem->name);
3496 if (namespace != NULL)
3497 fprintf(output, "ns %s", namespace);
3498 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003499 fprintf(output, "\n");
3500 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003501 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003502 if (elem->maxOccurs >= UNBOUNDED)
3503 fprintf(output, "max: unbounded\n");
3504 else if (elem->maxOccurs != 1)
3505 fprintf(output, "max: %d\n", elem->maxOccurs);
3506 else
3507 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003508 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003509 /*
3510 * Misc other properties.
3511 */
3512 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3513 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3514 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3515 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3516 (elem->id != NULL)) {
3517 fprintf(output, " props: ");
3518 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3519 fprintf(output, "[fixed] ");
3520 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3521 fprintf(output, "[default] ");
3522 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3523 fprintf(output, "[abstract] ");
3524 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3525 fprintf(output, "[nillable] ");
3526 if (elem->id != NULL)
3527 fprintf(output, "[id: '%s'] ", elem->id);
3528 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003529 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003530 /*
3531 * Default/fixed value.
3532 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003533 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003534 fprintf(output, " value: '%s'\n", elem->value);
3535 /*
3536 * Type.
3537 */
3538 if (elem->namedType != NULL) {
3539 fprintf(output, " type: %s ", elem->namedType);
3540 if (elem->namedTypeNs != NULL)
3541 fprintf(output, "ns %s\n", elem->namedTypeNs);
3542 else
3543 fprintf(output, "\n");
3544 }
3545 /*
3546 * Substitution group.
3547 */
3548 if (elem->substGroup != NULL) {
3549 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3550 if (elem->substGroupNs != NULL)
3551 fprintf(output, "ns %s\n", elem->substGroupNs);
3552 else
3553 fprintf(output, "\n");
3554 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003555}
3556
3557/**
3558 * xmlSchemaAnnotDump:
3559 * @output: the file output
3560 * @annot: a annotation
3561 *
3562 * Dump the annotation
3563 */
3564static void
3565xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3566{
3567 xmlChar *content;
3568
3569 if (annot == NULL)
3570 return;
3571
3572 content = xmlNodeGetContent(annot->content);
3573 if (content != NULL) {
3574 fprintf(output, " Annot: %s\n", content);
3575 xmlFree(content);
3576 } else
3577 fprintf(output, " Annot: empty\n");
3578}
3579
3580/**
3581 * xmlSchemaTypeDump:
3582 * @output: the file output
3583 * @type: a type structure
3584 *
3585 * Dump a SchemaType structure
3586 */
3587static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003588xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3589{
3590 xmlChar *str = NULL;
3591 xmlSchemaTreeItemPtr term;
3592 char shift[100];
3593 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003594
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003595 if (particle == NULL)
3596 return;
3597 for (i = 0;((i < depth) && (i < 25));i++)
3598 shift[2 * i] = shift[2 * i + 1] = ' ';
3599 shift[2 * i] = shift[2 * i + 1] = 0;
3600 fprintf(output, shift);
3601 if (particle->children == NULL) {
3602 fprintf(output, "MISSING particle term\n");
3603 return;
3604 }
3605 term = particle->children;
3606 switch (term->type) {
3607 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003608 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003609 ((xmlSchemaElementPtr)term)->targetNamespace,
3610 ((xmlSchemaElementPtr)term)->name));
3611 break;
3612 case XML_SCHEMA_TYPE_SEQUENCE:
3613 fprintf(output, "SEQUENCE");
3614 break;
3615 case XML_SCHEMA_TYPE_CHOICE:
3616 fprintf(output, "CHOICE");
3617 break;
3618 case XML_SCHEMA_TYPE_ALL:
3619 fprintf(output, "ALL");
3620 break;
3621 case XML_SCHEMA_TYPE_ANY:
3622 fprintf(output, "ANY");
3623 break;
3624 default:
3625 fprintf(output, "UNKNOWN\n");
3626 return;
3627 }
3628 if (particle->minOccurs != 1)
3629 fprintf(output, " min: %d", particle->minOccurs);
3630 if (particle->maxOccurs >= UNBOUNDED)
3631 fprintf(output, " max: unbounded");
3632 else if (particle->maxOccurs != 1)
3633 fprintf(output, " max: %d", particle->maxOccurs);
3634 fprintf(output, "\n");
3635 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3636 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3637 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3638 (term->children != NULL)) {
3639 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3640 output, depth +1);
3641 }
3642 if (particle->next != NULL)
3643 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3644 output, depth);
3645}
3646/**
3647 * xmlSchemaTypeDump:
3648 * @output: the file output
3649 * @type: a type structure
3650 *
3651 * Dump a SchemaType structure
3652 */
3653static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003654xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3655{
3656 if (type == NULL) {
3657 fprintf(output, "Type: NULL\n");
3658 return;
3659 }
3660 fprintf(output, "Type: ");
3661 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003662 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003663 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003664 fprintf(output, "no name ");
3665 if (type->targetNamespace != NULL)
3666 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003667 switch (type->type) {
3668 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003669 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003670 break;
3671 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003672 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003673 break;
3674 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003675 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003676 break;
3677 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003678 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 break;
3680 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003681 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003682 break;
3683 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003684 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 break;
3686 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003687 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 break;
3689 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003690 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003691 break;
3692 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003693 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003694 break;
3695 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003696 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003697 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003698 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003699 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003700 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003701 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003702 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003703 break;
3704 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003705 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003706 break;
3707 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003708 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003709 break;
3710 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003711 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003712 break;
3713 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003714 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003715 break;
3716 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003717 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003718 break;
3719 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003720 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 break;
3722 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003723 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003724 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003725 }
3726 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003727 if (type->base != NULL) {
3728 fprintf(output, " base type: %s", type->base);
3729 if (type->baseNs != NULL)
3730 fprintf(output, " ns %s\n", type->baseNs);
3731 else
3732 fprintf(output, "\n");
3733 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003734 if (type->annot != NULL)
3735 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003736#ifdef DUMP_CONTENT_MODEL
3737 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3738 (type->subtypes != NULL)) {
3739 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3740 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003741 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003742#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003743}
3744
3745/**
3746 * xmlSchemaDump:
3747 * @output: the file output
3748 * @schema: a schema structure
3749 *
3750 * Dump a Schema structure.
3751 */
3752void
3753xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3754{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003755 if (output == NULL)
3756 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003757 if (schema == NULL) {
3758 fprintf(output, "Schemas: NULL\n");
3759 return;
3760 }
3761 fprintf(output, "Schemas: ");
3762 if (schema->name != NULL)
3763 fprintf(output, "%s, ", schema->name);
3764 else
3765 fprintf(output, "no name, ");
3766 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003767 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003768 else
3769 fprintf(output, "no target namespace");
3770 fprintf(output, "\n");
3771 if (schema->annot != NULL)
3772 xmlSchemaAnnotDump(output, schema->annot);
3773
3774 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3775 output);
3776 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003777 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003778}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003779
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003780#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003781/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003782 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003783 * @vctxt: the WXS validation context
3784 *
3785 * Displays the current IDC table for debug purposes.
3786 */
3787static void
3788xmlSchemaDebugDumpIDCTable(FILE * output,
3789 const xmlChar *namespaceName,
3790 const xmlChar *localName,
3791 xmlSchemaPSVIIDCBindingPtr bind)
3792{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003793 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003794 xmlSchemaPSVIIDCNodePtr tab;
3795 xmlSchemaPSVIIDCKeyPtr key;
3796 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003797
3798 fprintf(output, "IDC: TABLES on %s\n",
3799 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003800 FREE_AND_NULL(str)
3801
3802 if (bind == NULL)
3803 return;
3804 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003805 fprintf(output, "IDC: BINDING %s\n",
3806 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003807 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003808 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003809 for (i = 0; i < bind->nbNodes; i++) {
3810 tab = bind->nodeTable[i];
3811 fprintf(output, " ( ");
3812 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003813 key = tab->keys[j];
3814 if ((key != NULL) && (key->val != NULL)) {
3815 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003816 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003817 fprintf(output, "\"%s\" ", value);
3818 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003819 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003820 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003821 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003822 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003823 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003824 else
3825 fprintf(output, "(key missing), ");
3826 }
3827 fprintf(output, ")\n");
3828 }
3829 bind = bind->next;
3830 } while (bind != NULL);
3831}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003832#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003833#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003834
3835/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003836 * *
3837 * Utilities *
3838 * *
3839 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003840
Daniel Veillardc0826a72004-08-10 14:17:33 +00003841/**
3842 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003843 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003844 * @name: the name of the attribute
3845 *
3846 * Seeks an attribute with a name of @name in
3847 * no namespace.
3848 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003849 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003850 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003851static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003852xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003853{
3854 xmlAttrPtr prop;
3855
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003856 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003857 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003858 prop = node->properties;
3859 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003860 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003861 return(prop);
3862 prop = prop->next;
3863 }
3864 return (NULL);
3865}
3866
3867/**
3868 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003869 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003870 * @uri: the uri
3871 * @name: the name of the attribute
3872 *
3873 * Seeks an attribute with a local name of @name and
3874 * a namespace URI of @uri.
3875 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003876 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003877 */
3878static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003879xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003880{
3881 xmlAttrPtr prop;
3882
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003883 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003884 return(NULL);
3885 prop = node->properties;
3886 while (prop != NULL) {
3887 if ((prop->ns != NULL) &&
3888 xmlStrEqual(prop->name, BAD_CAST name) &&
3889 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003890 return(prop);
3891 prop = prop->next;
3892 }
3893 return (NULL);
3894}
3895
3896static const xmlChar *
3897xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3898{
3899 xmlChar *val;
3900 const xmlChar *ret;
3901
3902 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003903 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003904 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003905 ret = xmlDictLookup(ctxt->dict, val, -1);
3906 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003907 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003908}
3909
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003910/**
3911 * xmlSchemaGetProp:
3912 * @ctxt: the parser context
3913 * @node: the node
3914 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003915 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003916 * Read a attribute value and internalize the string
3917 *
3918 * Returns the string or NULL if not present.
3919 */
3920static const xmlChar *
3921xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3922 const char *name)
3923{
3924 xmlChar *val;
3925 const xmlChar *ret;
3926
3927 val = xmlGetProp(node, BAD_CAST name);
3928 if (val == NULL)
3929 return(NULL);
3930 ret = xmlDictLookup(ctxt->dict, val, -1);
3931 xmlFree(val);
3932 return(ret);
3933}
3934
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003935/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003936 * *
3937 * Parsing functions *
3938 * *
3939 ************************************************************************/
3940
3941/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003942 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003943 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003944 * @name: the element name
3945 * @ns: the element namespace
3946 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003947 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003948 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003949 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003950 */
3951static xmlSchemaElementPtr
3952xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003953 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003954{
3955 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003956
3957 if ((name == NULL) || (schema == NULL))
3958 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003959
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003960 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003961 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003962 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003963 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003964 } else
3965 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003966 /*
3967 * This one was removed, since top level element declarations have
3968 * the target namespace specified in targetNamespace of the <schema>
3969 * information element, even if elementFormDefault is "unqualified".
3970 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003971
William M. Bracke7091952004-05-11 15:09:58 +00003972 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003973 if (xmlStrEqual(namespace, schema->targetNamespace))
3974 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3975 else
3976 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003977 if ((ret != NULL) &&
3978 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003979 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003980 }
William M. Bracke7091952004-05-11 15:09:58 +00003981 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003982
William M. Brack2f2a6632004-08-20 23:09:47 +00003983 /*
3984 * Removed since imported components will be hold by the main schema only.
3985 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003986 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003987 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003988 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003989 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003990 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003991 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003992 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3993 return (ret);
3994 } else
3995 ret = NULL;
3996 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003997 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003998#ifdef DEBUG
3999 if (ret == NULL) {
4000 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004001 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004002 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004003 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004004 namespace);
4005 }
4006#endif
4007 return (ret);
4008}
4009
4010/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004011 * xmlSchemaGetType:
4012 * @schema: the schemas context
4013 * @name: the type name
4014 * @ns: the type namespace
4015 *
4016 * Lookup a type in the schemas or the predefined types
4017 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004018 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004019 */
4020static xmlSchemaTypePtr
4021xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004022 const xmlChar * namespace)
4023{
Daniel Veillard4255d502002-04-16 15:50:10 +00004024 xmlSchemaTypePtr ret;
4025
4026 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004027 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004028 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004029 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004030 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004031 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004032 }
4033 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00004034 if (ret != NULL)
4035 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004036 /*
4037 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004038 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00004039 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004040 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004041 else
Daniel Veillard1d913862003-11-21 00:28:39 +00004042 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004043 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00004044 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004045 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4046 return (ret);
4047 } else
4048 ret = NULL;
4049 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004050 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004051#ifdef DEBUG
4052 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004053 if (namespace == NULL)
4054 fprintf(stderr, "Unable to lookup type %s", name);
4055 else
4056 fprintf(stderr, "Unable to lookup type %s:%s", name,
4057 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004058 }
4059#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004060 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004061}
4062
Daniel Veillard3646d642004-06-02 19:19:14 +00004063/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004064 * xmlSchemaGetAttributeDecl:
4065 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004066 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004067 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004068 *
4069 * Lookup a an attribute in the schema or imported schemas
4070 *
4071 * Returns the attribute declaration or NULL if not found.
4072 */
4073static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004074xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004075 const xmlChar * namespace)
4076{
4077 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004078
4079 if ((name == NULL) || (schema == NULL))
4080 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004081
4082
Daniel Veillard3646d642004-06-02 19:19:14 +00004083 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4084 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004085 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004086 else
4087 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004088 /*
4089 * Removed, since imported components will be hold by the main schema only.
4090 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004091 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004092 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004093 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004094 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004095 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004096 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004097 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4098 return (ret);
4099 } else
4100 ret = NULL;
4101 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004102 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004103#ifdef DEBUG
4104 if (ret == NULL) {
4105 if (namespace == NULL)
4106 fprintf(stderr, "Unable to lookup attribute %s", name);
4107 else
4108 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4109 namespace);
4110 }
4111#endif
4112 return (ret);
4113}
4114
4115/**
4116 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004117 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004118 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004119 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004120 *
4121 * Lookup a an attribute group in the schema or imported schemas
4122 *
4123 * Returns the attribute group definition or NULL if not found.
4124 */
4125static xmlSchemaAttributeGroupPtr
4126xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4127 const xmlChar * namespace)
4128{
4129 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004130
4131 if ((name == NULL) || (schema == NULL))
4132 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004133
4134
Daniel Veillard3646d642004-06-02 19:19:14 +00004135 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4136 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004137 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004138 else
4139 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004140 /*
4141 * Removed since imported components will be hold by the main schema only.
4142 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004143 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004144 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004145 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004146 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004147 if (import != NULL) {
4148 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4149 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4150 return (ret);
4151 else
4152 ret = NULL;
4153 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004154 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004155#ifdef DEBUG
4156 if (ret == NULL) {
4157 if (namespace == NULL)
4158 fprintf(stderr, "Unable to lookup attribute group %s", name);
4159 else
4160 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4161 namespace);
4162 }
4163#endif
4164 return (ret);
4165}
4166
4167/**
4168 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004169 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004170 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004171 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004172 *
4173 * Lookup a group in the schema or imported schemas
4174 *
4175 * Returns the group definition or NULL if not found.
4176 */
4177static xmlSchemaTypePtr
4178xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4179 const xmlChar * namespace)
4180{
4181 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004182
4183 if ((name == NULL) || (schema == NULL))
4184 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004185
Daniel Veillard3646d642004-06-02 19:19:14 +00004186 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004187 /*
4188 * Removed since imported components will be hold by the main schema only.
4189 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004190 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004191 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004192 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004193 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004194 if (import != NULL) {
4195 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4196 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4197 return (ret);
4198 else
4199 ret = NULL;
4200 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004201 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004202#ifdef DEBUG
4203 if (ret == NULL) {
4204 if (namespace == NULL)
4205 fprintf(stderr, "Unable to lookup group %s", name);
4206 else
4207 fprintf(stderr, "Unable to lookup group %s:%s", name,
4208 namespace);
4209 }
4210#endif
4211 return (ret);
4212}
4213
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004214/**
4215 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004216 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004217 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004218 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004219 *
4220 * Lookup a group in the schema or imported schemas
4221 *
4222 * Returns the group definition or NULL if not found.
4223 */
4224static xmlSchemaTreeItemPtr
4225xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4226 xmlSchemaTypeType itemType,
4227 const xmlChar *name,
4228 const xmlChar *targetNs)
4229{
4230 switch (itemType) {
4231 case XML_SCHEMA_TYPE_GROUP:
4232 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4233 name, targetNs));
4234 case XML_SCHEMA_TYPE_ELEMENT:
4235 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4236 name, targetNs));
4237 default:
4238 return (NULL);
4239 }
4240}
4241
Daniel Veillard4255d502002-04-16 15:50:10 +00004242/************************************************************************
4243 * *
4244 * Parsing functions *
4245 * *
4246 ************************************************************************/
4247
4248#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004249 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004250
4251/**
4252 * xmlSchemaIsBlank:
4253 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004254 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004255 *
4256 * Check if a string is ignorable
4257 *
4258 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4259 */
4260static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004261xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004262{
Daniel Veillard4255d502002-04-16 15:50:10 +00004263 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004264 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004265 if (len < 0) {
4266 while (*str != 0) {
4267 if (!(IS_BLANK_CH(*str)))
4268 return (0);
4269 str++;
4270 }
4271 } else while ((*str != 0) && (len != 0)) {
4272 if (!(IS_BLANK_CH(*str)))
4273 return (0);
4274 str++;
4275 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004276 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004277
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004278 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004279}
4280
4281/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004282 * xmlSchemaAddAssembledItem:
4283 * @ctxt: a schema parser context
4284 * @schema: the schema being built
4285 * @item: the item
4286 *
4287 * Add a item to the schema's list of current items.
4288 * This is used if the schema was already constructed and
4289 * new schemata need to be added to it.
4290 * *WARNING* this interface is highly subject to change.
4291 *
4292 * Returns 0 if suceeds and -1 if an internal error occurs.
4293 */
4294static int
4295xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4296 xmlSchemaTypePtr item)
4297{
4298 static int growSize = 100;
4299 xmlSchemaAssemblePtr ass;
4300
4301 ass = ctxt->assemble;
4302 if (ass->sizeItems < 0) {
4303 /* If disabled. */
4304 return (0);
4305 }
4306 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004307 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004308 if (ass->items == NULL) {
4309 xmlSchemaPErrMemory(ctxt,
4310 "allocating new item buffer", NULL);
4311 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004312 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004313 ass->sizeItems = growSize;
4314 } else if (ass->sizeItems <= ass->nbItems) {
4315 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004316 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004317 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4318 if (ass->items == NULL) {
4319 xmlSchemaPErrMemory(ctxt,
4320 "growing item buffer", NULL);
4321 ass->sizeItems = 0;
4322 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004323 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004324 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004325 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004326 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4327 return (0);
4328}
4329
4330/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004331 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004332 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004333 * @schema: the schema being built
4334 * @name: the item name
4335 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004336 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004337 * *WARNING* this interface is highly subject to change
4338 *
4339 * Returns the new struture or NULL in case of error
4340 */
4341static xmlSchemaNotationPtr
4342xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004343 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004344{
4345 xmlSchemaNotationPtr ret = NULL;
4346 int val;
4347
4348 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4349 return (NULL);
4350
4351 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004352 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004353 if (schema->notaDecl == NULL)
4354 return (NULL);
4355
4356 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4357 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004358 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004359 return (NULL);
4360 }
4361 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004362 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004363 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4364 ret);
4365 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004366 /*
4367 * TODO: This should never happen, since a unique name will be computed.
4368 * If it fails, then an other internal error must have occured.
4369 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004370 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4371 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004372 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004373 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004374 xmlFree(ret);
4375 return (NULL);
4376 }
4377 return (ret);
4378}
4379
4380
4381/**
4382 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004383 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004384 * @schema: the schema being built
4385 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004386 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004387 *
4388 * Add an XML schema Attrribute declaration
4389 * *WARNING* this interface is highly subject to change
4390 *
4391 * Returns the new struture or NULL in case of error
4392 */
4393static xmlSchemaAttributePtr
4394xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004395 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004396 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004397{
4398 xmlSchemaAttributePtr ret = NULL;
4399 int val;
4400
4401 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4402 return (NULL);
4403
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004404#ifdef DEBUG
4405 fprintf(stderr, "Adding attribute %s\n", name);
4406 if (namespace != NULL)
4407 fprintf(stderr, " target namespace %s\n", namespace);
4408#endif
4409
Daniel Veillard4255d502002-04-16 15:50:10 +00004410 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004411 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004412 if (schema->attrDecl == NULL)
4413 return (NULL);
4414
4415 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4416 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004417 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004418 return (NULL);
4419 }
4420 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004421 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004422 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004423 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004424 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004425 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004426 if (topLevel) {
4427 xmlSchemaPCustomErr(ctxt,
4428 XML_SCHEMAP_REDEFINED_ATTR,
4429 NULL, NULL, node,
4430 "A global attribute declaration with the name '%s' does "
4431 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004432 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004433 return (NULL);
4434 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004435 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004436 /*
4437 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4438 * in the scenario:
4439 * 1. multiple top-level complex types have different target
4440 * namespaces but have the SAME NAME; this can happen if
4441 * schemata are imported
4442 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004443 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004444 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004445 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004446 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004447 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004448 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004449
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004450 if (val != 0) {
4451 xmlSchemaPCustomErr(ctxt,
4452 XML_SCHEMAP_INTERNAL,
4453 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004454 "Internal error: xmlSchemaAddAttribute, "
4455 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004456 "could not be added to the hash.", name);
4457 xmlFree(ret);
4458 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004459 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004460 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004461 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004462 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004463 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004464 return (ret);
4465}
4466
4467/**
4468 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004469 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004470 * @schema: the schema being built
4471 * @name: the item name
4472 *
4473 * Add an XML schema Attrribute Group declaration
4474 *
4475 * Returns the new struture or NULL in case of error
4476 */
4477static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004478xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004479 xmlSchemaPtr schema, const xmlChar * name,
4480 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004481{
4482 xmlSchemaAttributeGroupPtr ret = NULL;
4483 int val;
4484
4485 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4486 return (NULL);
4487
4488 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004489 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004490 if (schema->attrgrpDecl == NULL)
4491 return (NULL);
4492
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004493 ret =
4494 (xmlSchemaAttributeGroupPtr)
4495 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004496 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004497 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004498 return (NULL);
4499 }
4500 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004501 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004504 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004505 xmlSchemaPCustomErr(ctxt,
4506 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4507 NULL, NULL, node,
4508 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004509 xmlFree(ret);
4510 return (NULL);
4511 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004512 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004513 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004514 return (ret);
4515}
4516
4517/**
4518 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004519 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004520 * @schema: the schema being built
4521 * @name: the type name
4522 * @namespace: the type namespace
4523 *
4524 * Add an XML schema Element declaration
4525 * *WARNING* this interface is highly subject to change
4526 *
4527 * Returns the new struture or NULL in case of error
4528 */
4529static xmlSchemaElementPtr
4530xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004531 const xmlChar * name, const xmlChar * namespace,
4532 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004533{
4534 xmlSchemaElementPtr ret = NULL;
4535 int val;
4536
4537 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4538 return (NULL);
4539
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004540#ifdef DEBUG
4541 fprintf(stderr, "Adding element %s\n", name);
4542 if (namespace != NULL)
4543 fprintf(stderr, " target namespace %s\n", namespace);
4544#endif
4545
Daniel Veillard4255d502002-04-16 15:50:10 +00004546 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004547 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004548 if (schema->elemDecl == NULL)
4549 return (NULL);
4550
4551 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4552 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004553 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004554 return (NULL);
4555 }
4556 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004557 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004558 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004559 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004560 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004561 if (topLevel) {
4562 xmlSchemaPCustomErr(ctxt,
4563 XML_SCHEMAP_REDEFINED_ELEMENT,
4564 NULL, NULL, node,
4565 "A global element declaration with the name '%s' does "
4566 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004567 xmlFree(ret);
4568 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004569 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004570 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004571
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004572 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004573 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004574 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004575 if (val != 0) {
4576 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004577 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004578 NULL, NULL, node,
4579 "Internal error: xmlSchemaAddElement, "
4580 "a dublicate element declaration with the name '%s' "
4581 "could not be added to the hash.", name);
4582 xmlFree(ret);
4583 return (NULL);
4584 }
4585 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004586
Daniel Veillard4255d502002-04-16 15:50:10 +00004587 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004588 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004589 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004590 return (ret);
4591}
4592
4593/**
4594 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004595 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004596 * @schema: the schema being built
4597 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004598 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004599 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004600 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004601 * *WARNING* this interface is highly subject to change
4602 *
4603 * Returns the new struture or NULL in case of error
4604 */
4605static xmlSchemaTypePtr
4606xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004607 const xmlChar * name, const xmlChar * namespace,
4608 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004609{
4610 xmlSchemaTypePtr ret = NULL;
4611 int val;
4612
4613 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4614 return (NULL);
4615
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004616#ifdef DEBUG
4617 fprintf(stderr, "Adding type %s\n", name);
4618 if (namespace != NULL)
4619 fprintf(stderr, " target namespace %s\n", namespace);
4620#endif
4621
Daniel Veillard4255d502002-04-16 15:50:10 +00004622 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004623 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004624 if (schema->typeDecl == NULL)
4625 return (NULL);
4626
4627 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4628 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004629 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004630 return (NULL);
4631 }
4632 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004633 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004634 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004635 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004636 if (val != 0) {
4637 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004638 xmlSchemaPCustomErr(ctxt,
4639 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004640 NULL, NULL, node,
4641 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004642 xmlFree(ret);
4643 return (NULL);
4644 } else {
4645 xmlSchemaTypePtr prev;
4646
4647 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4648 if (prev == NULL) {
4649 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004650 XML_ERR_INTERNAL_ERROR,
4651 "Internal error: xmlSchemaAddType, on type "
4652 "'%s'.\n",
4653 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004654 xmlFree(ret);
4655 return (NULL);
4656 }
4657 ret->redef = prev->redef;
4658 prev->redef = ret;
4659 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004660 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004661 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004662 ret->minOccurs = 1;
4663 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004664 ret->attributeUses = NULL;
4665 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004666 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004667 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004668 return (ret);
4669}
4670
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004671static xmlSchemaQNameRefPtr
4672xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4673 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004674 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004675 const xmlChar *refNs)
4676{
4677 xmlSchemaQNameRefPtr ret;
4678
4679 ret = (xmlSchemaQNameRefPtr)
4680 xmlMalloc(sizeof(xmlSchemaQNameRef));
4681 if (ret == NULL) {
4682 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4683 NULL);
4684 return (NULL);
4685 }
4686 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4687 ret->name = refName;
4688 ret->targetNamespace = refNs;
4689 ret->item = NULL;
4690 ret->itemType = refType;
4691 /*
4692 * Store the reference item in the schema.
4693 */
4694 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4695 return (ret);
4696}
4697
4698/**
4699 * xmlSchemaAddModelGroup:
4700 * @ctxt: a schema parser context
4701 * @schema: the schema being built
4702 * @type: the "compositor" type of the model group
4703 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004704 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004705 *
4706 * Adds a schema model group
4707 * *WARNING* this interface is highly subject to change
4708 *
4709 * Returns the new struture or NULL in case of error
4710 */
4711static xmlSchemaModelGroupPtr
4712xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4713 xmlSchemaTypeType type, const xmlChar **container,
4714 xmlNodePtr node)
4715{
4716 xmlSchemaModelGroupPtr ret = NULL;
4717 xmlChar buf[30];
4718
4719 if ((ctxt == NULL) || (schema == NULL))
4720 return (NULL);
4721
4722#ifdef DEBUG
4723 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004724#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004725 ret = (xmlSchemaModelGroupPtr)
4726 xmlMalloc(sizeof(xmlSchemaModelGroup));
4727 if (ret == NULL) {
4728 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4729 NULL);
4730 return (NULL);
4731 }
4732 ret->type = type;
4733 ret->annot = NULL;
4734 ret->node = node;
4735 ret->children = NULL;
4736 ret->next = NULL;
4737 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4738 if (container != NULL)
4739 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4740 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004741 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004742 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4743 } else {
4744 if (container != NULL)
4745 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4746 }
4747 if (container != NULL)
4748 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4749 /*
4750 * Add to volatile items.
4751 * TODO: this should be changed someday.
4752 */
4753 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4754 xmlFree(ret);
4755 return (NULL);
4756 }
4757 return (ret);
4758}
4759
4760
4761/**
4762 * xmlSchemaAddParticle:
4763 * @ctxt: a schema parser context
4764 * @schema: the schema being built
4765 * @node: the corresponding node in the schema doc
4766 * @min: the minOccurs
4767 * @max: the maxOccurs
4768 *
4769 * Adds an XML schema particle component.
4770 * *WARNING* this interface is highly subject to change
4771 *
4772 * Returns the new struture or NULL in case of error
4773 */
4774static xmlSchemaParticlePtr
4775xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4776 xmlNodePtr node, int min, int max)
4777{
4778 xmlSchemaParticlePtr ret = NULL;
4779 if ((ctxt == NULL) || (schema == NULL))
4780 return (NULL);
4781
4782#ifdef DEBUG
4783 fprintf(stderr, "Adding particle component\n");
4784#endif
4785 ret = (xmlSchemaParticlePtr)
4786 xmlMalloc(sizeof(xmlSchemaParticle));
4787 if (ret == NULL) {
4788 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4789 NULL);
4790 return (NULL);
4791 }
4792 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4793 ret->annot = NULL;
4794 ret->node = node;
4795 ret->minOccurs = min;
4796 ret->maxOccurs = max;
4797 ret->next = NULL;
4798 ret->children = NULL;
4799
4800 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4801 xmlFree(ret);
4802 return (NULL);
4803 }
4804 return (ret);
4805}
4806
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004807/**
4808 * xmlSchemaAddGroup:
4809 * @ctxt: a schema validation context
4810 * @schema: the schema being built
4811 * @name: the group name
4812 *
4813 * Add an XML schema Group definition
4814 *
4815 * Returns the new struture or NULL in case of error
4816 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004817static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004818xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004819 const xmlChar *name, const xmlChar *namespaceName,
4820 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004821{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004822 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004823 int val;
4824
4825 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4826 return (NULL);
4827
4828 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004829 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004830 if (schema->groupDecl == NULL)
4831 return (NULL);
4832
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004833 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004834 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004835 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004836 return (NULL);
4837 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004838 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004839 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004840 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004841 ret->node = node;
4842 ret->targetNamespace = namespaceName;
4843 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004844 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004845 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004846 XML_SCHEMAP_REDEFINED_GROUP,
4847 NULL, NULL, node,
4848 "A global model group definition with the name '%s' does already "
4849 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004850 xmlFree(ret);
4851 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004852 }
4853 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004854 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004855 return (ret);
4856}
4857
Daniel Veillard3646d642004-06-02 19:19:14 +00004858/**
4859 * xmlSchemaNewWildcardNs:
4860 * @ctxt: a schema validation context
4861 *
4862 * Creates a new wildcard namespace constraint.
4863 *
4864 * Returns the new struture or NULL in case of error
4865 */
4866static xmlSchemaWildcardNsPtr
4867xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4868{
4869 xmlSchemaWildcardNsPtr ret;
4870
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004871 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004872 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4873 if (ret == NULL) {
4874 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004875 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004876 }
4877 ret->value = NULL;
4878 ret->next = NULL;
4879 return (ret);
4880}
4881
4882/**
4883 * xmlSchemaAddWildcard:
4884 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004885 * @schema: a schema
4886 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004887 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004888 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004889 *
4890 * Returns the new struture or NULL in case of error
4891 */
4892static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004893xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4894 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004895{
4896 xmlSchemaWildcardPtr ret = NULL;
4897
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004898 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004899 return (NULL);
4900
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004901#ifdef DEBUG
4902 fprintf(stderr, "Adding wildcard component\n");
4903#endif
4904
Daniel Veillard3646d642004-06-02 19:19:14 +00004905 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4906 if (ret == NULL) {
4907 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4908 return (NULL);
4909 }
4910 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004911 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004912 ret->minOccurs = 1;
4913 ret->maxOccurs = 1;
4914
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004915 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4916 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4917 "Failed to add a wildcard component to the list", NULL);
4918 xmlFree(ret);
4919 return (NULL);
4920 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004921 return (ret);
4922}
4923
Daniel Veillard4255d502002-04-16 15:50:10 +00004924/************************************************************************
4925 * *
4926 * Utilities for parsing *
4927 * *
4928 ************************************************************************/
4929
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004930#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004931/**
4932 * xmlGetQNameProp:
4933 * @ctxt: a schema validation context
4934 * @node: a subtree containing XML Schema informations
4935 * @name: the attribute name
4936 * @namespace: the result namespace if any
4937 *
4938 * Extract a QName Attribute value
4939 *
4940 * Returns the NCName or NULL if not found, and also update @namespace
4941 * with the namespace URI
4942 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004943static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004944xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004945 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004946{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004947 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004948 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004949 const xmlChar *ret, *prefix;
4950 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004951 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004952
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004953 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004954 attr = xmlSchemaGetPropNode(node, name);
4955 if (attr == NULL)
4956 return (NULL);
4957 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004958
Daniel Veillard4255d502002-04-16 15:50:10 +00004959 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004960 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004961
Daniel Veillardba0153a2004-04-01 10:42:31 +00004962 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004963 ns = xmlSearchNs(node->doc, node, 0);
4964 if (ns) {
4965 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4966 return (val);
4967 }
4968 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004969 ret = xmlSplitQName3(val, &len);
4970 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004971 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004972 }
4973 ret = xmlDictLookup(ctxt->dict, ret, -1);
4974 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004975
4976 ns = xmlSearchNs(node->doc, node, prefix);
4977 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004978 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4979 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004980 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004981 "The QName value '%s' has no corresponding namespace "
4982 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004983 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004984 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004985 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004986 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004987}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004988#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004989
4990/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 * xmlSchemaPValAttrNodeQNameValue:
4992 * @ctxt: a schema parser context
4993 * @schema: the schema context
4994 * @ownerDes: the designation of the parent element
4995 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004996 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004997 * @local: the resulting local part if found, the attribute value otherwise
4998 * @uri: the resulting namespace URI if found
4999 *
5000 * Extracts the local name and the URI of a QName value and validates it.
5001 * This one is intended to be used on attribute values that
5002 * should resolve to schema components.
5003 *
5004 * Returns 0, in case the QName is valid, a positive error code
5005 * if not valid and -1 if an internal error occurs.
5006 */
5007static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005008xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005009 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005010 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005011 xmlSchemaTypePtr ownerItem,
5012 xmlAttrPtr attr,
5013 const xmlChar *value,
5014 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005015 const xmlChar **local)
5016{
5017 const xmlChar *pref;
5018 xmlNsPtr ns;
5019 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005020
Daniel Veillardc0826a72004-08-10 14:17:33 +00005021 *uri = NULL;
5022 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005023 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005024 if (ret > 0) {
5025 xmlSchemaPSimpleTypeErr(ctxt,
5026 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5027 ownerItem, (xmlNodePtr) attr,
5028 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5029 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005030 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005031 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005032 } else if (ret < 0)
5033 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005034
5035 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005036 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005037 if (ns)
5038 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5039 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5040 /*
5041 * This one takes care of included schemas with no
5042 * target namespace.
5043 */
5044 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005045 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005046 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005047 return (0);
5048 }
5049 /*
5050 * At this point xmlSplitQName3 has to return a local name.
5051 */
5052 *local = xmlSplitQName3(value, &len);
5053 *local = xmlDictLookup(ctxt->dict, *local, -1);
5054 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005055 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5056 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005057 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005058 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005059 ownerItem, (xmlNodePtr) attr,
5060 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5061 "The value '%s' of simple type 'xs:QName' has no "
5062 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005063 return (ctxt->err);
5064 } else {
5065 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005066 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005067 return (0);
5068}
5069
5070/**
5071 * xmlSchemaPValAttrNodeQName:
5072 * @ctxt: a schema parser context
5073 * @schema: the schema context
5074 * @ownerDes: the designation of the owner element
5075 * @ownerItem: the owner as a schema object
5076 * @attr: the attribute node
5077 * @local: the resulting local part if found, the attribute value otherwise
5078 * @uri: the resulting namespace URI if found
5079 *
5080 * Extracts and validates the QName of an attribute value.
5081 * This one is intended to be used on attribute values that
5082 * should resolve to schema components.
5083 *
5084 * Returns 0, in case the QName is valid, a positive error code
5085 * if not valid and -1 if an internal error occurs.
5086 */
5087static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005088xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005089 xmlSchemaPtr schema,
5090 xmlChar **ownerDes,
5091 xmlSchemaTypePtr ownerItem,
5092 xmlAttrPtr attr,
5093 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005094 const xmlChar **local)
5095{
5096 const xmlChar *value;
5097
5098 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005099 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5100 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005101}
5102
5103/**
5104 * xmlSchemaPValAttrQName:
5105 * @ctxt: a schema parser context
5106 * @schema: the schema context
5107 * @ownerDes: the designation of the parent element
5108 * @ownerItem: the owner as a schema object
5109 * @ownerElem: the parent node of the attribute
5110 * @name: the name of the attribute
5111 * @local: the resulting local part if found, the attribute value otherwise
5112 * @uri: the resulting namespace URI if found
5113 *
5114 * Extracts and validates the QName of an attribute value.
5115 *
5116 * Returns 0, in case the QName is valid, a positive error code
5117 * if not valid and -1 if an internal error occurs.
5118 */
5119static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005120xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5121 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005122 xmlChar **ownerDes,
5123 xmlSchemaTypePtr ownerItem,
5124 xmlNodePtr ownerElem,
5125 const char *name,
5126 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005127 const xmlChar **local)
5128{
5129 xmlAttrPtr attr;
5130
5131 attr = xmlSchemaGetPropNode(ownerElem, name);
5132 if (attr == NULL) {
5133 *local = NULL;
5134 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005135 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005136 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005137 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5138 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005139}
5140
5141/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005142 * xmlSchemaPValAttrID:
5143 * @ctxt: a schema parser context
5144 * @schema: the schema context
5145 * @ownerDes: the designation of the parent element
5146 * @ownerItem: the owner as a schema object
5147 * @ownerElem: the parent node of the attribute
5148 * @name: the name of the attribute
5149 *
5150 * Extracts and validates the ID of an attribute value.
5151 *
5152 * Returns 0, in case the ID is valid, a positive error code
5153 * if not valid and -1 if an internal error occurs.
5154 */
5155static int
5156xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005157 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005158 xmlSchemaTypePtr ownerItem,
5159 xmlNodePtr ownerElem,
5160 const xmlChar *name)
5161{
5162 int ret;
5163 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005164 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005165
5166 value = xmlGetNoNsProp(ownerElem, name);
5167 if (value == NULL)
5168 return (0);
5169
5170 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5171 if (attr == NULL)
5172 return (-1);
5173
5174 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005175 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005176 /*
5177 * NOTE: the IDness might have already be declared in the DTD
5178 */
5179 if (attr->atype != XML_ATTRIBUTE_ID) {
5180 xmlIDPtr res;
5181 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005182
5183 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005184 * TODO: Use xmlSchemaStrip here; it's not exported at this
5185 * moment.
5186 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005187 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005188 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005189 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005190 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5191 if (res == NULL) {
5192 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005193 xmlSchemaPSimpleTypeErr(ctxt,
5194 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5195 ownerItem, (xmlNodePtr) attr,
5196 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5197 NULL, NULL, "Duplicate value '%s' of simple "
5198 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005199 } else
5200 attr->atype = XML_ATTRIBUTE_ID;
5201 if (strip != NULL)
5202 xmlFree(strip);
5203 }
5204 } else if (ret > 0) {
5205 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005206 xmlSchemaPSimpleTypeErr(ctxt,
5207 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5208 ownerItem, (xmlNodePtr) attr,
5209 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5210 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5211 "not a valid 'xs:NCName'",
5212 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005213 }
5214 xmlFree(value);
5215
5216 return (ret);
5217}
5218
5219/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005220 * xmlGetMaxOccurs:
5221 * @ctxt: a schema validation context
5222 * @node: a subtree containing XML Schema informations
5223 *
5224 * Get the maxOccurs property
5225 *
5226 * Returns the default if not found, or the value
5227 */
5228static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005229xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5230 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005231{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005232 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005233 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005234 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005235
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005236 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5237 if (attr == NULL)
5238 return (def);
5239 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005240
5241 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005242 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005243 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005244 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5245 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005246 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005247 val, NULL, NULL, NULL);
5248 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005249 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005250 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005251 }
5252
5253 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005254 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005255 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005256 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005257 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005258 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5259 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005260 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005261 val, NULL, NULL, NULL);
5262 return (def);
5263 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005264 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005265 ret = ret * 10 + (*cur - '0');
5266 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005267 }
William M. Brack76e95df2003-10-18 16:20:14 +00005268 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005269 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005270 /*
5271 * TODO: Restrict the maximal value to Integer.
5272 */
5273 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005274 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005275 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5276 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005277 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005278 val, NULL, NULL, NULL);
5279 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005280 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005281 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005282}
5283
5284/**
5285 * xmlGetMinOccurs:
5286 * @ctxt: a schema validation context
5287 * @node: a subtree containing XML Schema informations
5288 *
5289 * Get the minOccurs property
5290 *
5291 * Returns the default if not found, or the value
5292 */
5293static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005294xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005295 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005296{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005297 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005298 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005299 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005300
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005301 attr = xmlSchemaGetPropNode(node, "minOccurs");
5302 if (attr == NULL)
5303 return (def);
5304 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005305 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005306 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005307 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005308 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005309 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005310 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5311 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005312 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005313 val, NULL, NULL, NULL);
5314 return (def);
5315 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005316 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005317 ret = ret * 10 + (*cur - '0');
5318 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005319 }
William M. Brack76e95df2003-10-18 16:20:14 +00005320 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005321 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005322 /*
5323 * TODO: Restrict the maximal value to Integer.
5324 */
5325 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005326 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005327 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5328 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005329 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005330 val, NULL, NULL, NULL);
5331 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005332 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005333 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005334}
5335
5336/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005337 * xmlSchemaPGetBoolNodeValue:
5338 * @ctxt: a schema validation context
5339 * @ownerDes: owner designation
5340 * @ownerItem: the owner as a schema item
5341 * @node: the node holding the value
5342 *
5343 * Converts a boolean string value into 1 or 0.
5344 *
5345 * Returns 0 or 1.
5346 */
5347static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005348xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5349 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005350 xmlSchemaTypePtr ownerItem,
5351 xmlNodePtr node)
5352{
5353 xmlChar *value = NULL;
5354 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005355
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005356 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005357 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005358 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005359 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005360 * can have the following legal literals {true, false, 1, 0}.
5361 */
5362 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5363 res = 1;
5364 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5365 res = 0;
5366 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5367 res = 1;
5368 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005369 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005370 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005371 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005372 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005373 ownerItem, node,
5374 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5375 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005376 NULL, NULL, NULL);
5377 }
5378 if (value != NULL)
5379 xmlFree(value);
5380 return (res);
5381}
5382
5383/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005384 * xmlGetBooleanProp:
5385 * @ctxt: a schema validation context
5386 * @node: a subtree containing XML Schema informations
5387 * @name: the attribute name
5388 * @def: the default value
5389 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005390 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005391 *
5392 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005393 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005394 */
5395static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005396xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5397 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005398 xmlSchemaTypePtr ownerItem,
5399 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005400 const char *name, int def)
5401{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005402 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005403
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005404 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005405 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005406 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005407 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005408 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005409 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005410 * can have the following legal literals {true, false, 1, 0}.
5411 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005412 if (xmlStrEqual(val, BAD_CAST "true"))
5413 def = 1;
5414 else if (xmlStrEqual(val, BAD_CAST "false"))
5415 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005416 else if (xmlStrEqual(val, BAD_CAST "1"))
5417 def = 1;
5418 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005419 def = 0;
5420 else {
5421 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005422 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005423 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005424 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005425 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5426 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005427 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005428 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005429}
5430
5431/************************************************************************
5432 * *
5433 * Shema extraction from an Infoset *
5434 * *
5435 ************************************************************************/
5436static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5437 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005438 xmlNodePtr node,
5439 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005440static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5441 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005442 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005443 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005444 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005445static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5446 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005447 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005448 xmlNodePtr node,
5449 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005450static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5451 ctxt,
5452 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005453 xmlNodePtr node,
5454 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005455static xmlSchemaAttributeGroupPtr
5456xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005457 xmlSchemaPtr schema, xmlNodePtr node,
5458 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005459static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5460 xmlSchemaPtr schema,
5461 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005462static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005463xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5464 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005465
5466/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005467 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005468 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005469 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005470 * @ownerDes: the designation of the parent element
5471 * @ownerItem: the schema object owner if existent
5472 * @attr: the schema attribute node being validated
5473 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005474 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005475 *
5476 * Validates a value against the given built-in type.
5477 * This one is intended to be used internally for validation
5478 * of schema attribute values during parsing of the schema.
5479 *
5480 * Returns 0 if the value is valid, a positive error code
5481 * number otherwise and -1 in case of an internal or API error.
5482 */
5483static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005484xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5485 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5486 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005487 xmlAttrPtr attr,
5488 const xmlChar *value,
5489 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005490{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005491
5492 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005493
5494 /*
5495 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5496 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005497 */
5498 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005499 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005500 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5501 PERROR_INT("xmlSchemaPValAttrNodeValue",
5502 "the given type is not a built-in type");
5503 return (-1);
5504 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005505 switch (type->builtInType) {
5506 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005507 case XML_SCHEMAS_QNAME:
5508 case XML_SCHEMAS_ANYURI:
5509 case XML_SCHEMAS_TOKEN:
5510 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005511 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5512 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005513 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005514 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005515 PERROR_INT("xmlSchemaPValAttrNodeValue",
5516 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005517 return (-1);
5518 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005519 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005520 /*
5521 * TODO: Should we use the S4S error codes instead?
5522 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005523 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005524 PERROR_INT("xmlSchemaPValAttrNodeValue",
5525 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005526 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005527 } else if (ret > 0) {
5528 if (VARIETY_LIST(type))
5529 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5530 else
5531 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5532 xmlSchemaPSimpleTypeErr(pctxt,
5533 ret, ownerItem, (xmlNodePtr) attr,
5534 type, NULL, value, NULL, NULL, NULL);
5535 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005536 return (ret);
5537}
5538
5539/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005540 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005541 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005542 * @ctxt: a schema parser context
5543 * @ownerDes: the designation of the parent element
5544 * @ownerItem: the schema object owner if existent
5545 * @attr: the schema attribute node being validated
5546 * @type: the built-in type to be validated against
5547 * @value: the resulting value if any
5548 *
5549 * Extracts and validates a value against the given built-in type.
5550 * This one is intended to be used internally for validation
5551 * of schema attribute values during parsing of the schema.
5552 *
5553 * Returns 0 if the value is valid, a positive error code
5554 * number otherwise and -1 in case of an internal or API error.
5555 */
5556static int
5557xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5558 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005559 xmlSchemaTypePtr ownerItem,
5560 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 xmlSchemaTypePtr type,
5562 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005563{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005564 const xmlChar *val;
5565
5566 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005567 return (-1);
5568
Daniel Veillardc0826a72004-08-10 14:17:33 +00005569 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5570 if (value != NULL)
5571 *value = val;
5572
5573 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005574 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005575}
5576
5577/**
5578 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005579 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005580 * @ctxt: a schema parser context
5581 * @node: the element node of the attribute
5582 * @ownerDes: the designation of the parent element
5583 * @ownerItem: the schema object owner if existent
5584 * @ownerElem: the owner element node
5585 * @name: the name of the schema attribute node
5586 * @type: the built-in type to be validated against
5587 * @value: the resulting value if any
5588 *
5589 * Extracts and validates a value against the given built-in type.
5590 * This one is intended to be used internally for validation
5591 * of schema attribute values during parsing of the schema.
5592 *
5593 * Returns 0 if the value is valid, a positive error code
5594 * number otherwise and -1 in case of an internal or API error.
5595 */
5596static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005597xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005598 xmlChar **ownerDes,
5599 xmlSchemaTypePtr ownerItem,
5600 xmlNodePtr ownerElem,
5601 const char *name,
5602 xmlSchemaTypePtr type,
5603 const xmlChar **value)
5604{
5605 xmlAttrPtr attr;
5606
5607 if ((ctxt == NULL) || (type == NULL)) {
5608 if (value != NULL)
5609 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005610 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005611 }
5612 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5613 if (value != NULL)
5614 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005615 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005616 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005617 "Internal error: xmlSchemaPValAttr, the given "
5618 "type '%s' is not a built-in type.\n",
5619 type->name, NULL);
5620 return (-1);
5621 }
5622 attr = xmlSchemaGetPropNode(ownerElem, name);
5623 if (attr == NULL) {
5624 if (value != NULL)
5625 *value = NULL;
5626 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005627 }
5628 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005629 type, value));
5630}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005631
5632static int
5633xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5634 xmlSchemaPtr schema,
5635 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005636 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005637 const xmlChar *namespaceName)
5638{
5639 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005640 return (1);
5641 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5642 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005643 if (pctxt->localImports != NULL) {
5644 int i;
5645 for (i = 0; i < pctxt->nbLocalImports; i++)
5646 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5647 return (1);
5648 }
5649 if (namespaceName == NULL)
5650 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005651 NULL, (xmlSchemaTypePtr) item, node,
5652 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005653 "namespace are not valid, since not indicated by an import "
5654 "statement", NULL);
5655 else
5656 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005657 NULL, (xmlSchemaTypePtr) item, node,
5658 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005659 "namespace '%s' are not valid, since not indicated by an import "
5660 "statement", namespaceName);
5661 return (0);
5662}
5663
Daniel Veillardc0826a72004-08-10 14:17:33 +00005664/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005665 * xmlSchemaParseAttrDecls:
5666 * @ctxt: a schema validation context
5667 * @schema: the schema being built
5668 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005669 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005670 *
5671 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005672 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005673 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5674 */
5675static xmlNodePtr
5676xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5677 xmlNodePtr child, xmlSchemaTypePtr type)
5678{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005679 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005680
Daniel Veillard4255d502002-04-16 15:50:10 +00005681 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005682 (IS_SCHEMA(child, "attributeGroup"))) {
5683 attr = NULL;
5684 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005685 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005686 } else if (IS_SCHEMA(child, "attributeGroup")) {
5687 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005688 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005689 }
5690 if (attr != NULL) {
5691 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005692 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5693 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5694 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005695 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005696 lastattr = attr;
5697 } else {
5698 lastattr->next = attr;
5699 lastattr = attr;
5700 }
5701 }
5702 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005703 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005704 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005705}
5706
5707/**
5708 * xmlSchemaParseAnnotation:
5709 * @ctxt: a schema validation context
5710 * @schema: the schema being built
5711 * @node: a subtree containing XML Schema informations
5712 *
5713 * parse a XML schema Attrribute declaration
5714 * *WARNING* this interface is highly subject to change
5715 *
William M. Bracke7091952004-05-11 15:09:58 +00005716 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005717 * 1 in case of success.
5718 */
5719static xmlSchemaAnnotPtr
5720xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5721 xmlNodePtr node)
5722{
5723 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 xmlNodePtr child = NULL;
5725 xmlAttrPtr attr;
5726 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005727
Daniel Veillardc0826a72004-08-10 14:17:33 +00005728 /*
5729 * INFO: S4S completed.
5730 */
5731 /*
5732 * id = ID
5733 * {any attributes with non-schema namespace . . .}>
5734 * Content: (appinfo | documentation)*
5735 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005736 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5737 return (NULL);
5738 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005739 attr = node->properties;
5740 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005741 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005742 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005743 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005744 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005745
5746 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005747 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5748 NULL, NULL, attr);
5749 }
5750 attr = attr->next;
5751 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005752 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005753 /*
5754 * And now for the children...
5755 */
5756 child = node->children;
5757 while (child != NULL) {
5758 if (IS_SCHEMA(child, "appinfo")) {
5759 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005760 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005761 * source = anyURI
5762 * {any attributes with non-schema namespace . . .}>
5763 * Content: ({any})*
5764 */
5765 attr = child->properties;
5766 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005767 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005768 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005769 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005770 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005771
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005772 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005773 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5774 NULL, NULL, attr);
5775 }
5776 attr = attr->next;
5777 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005778 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5779 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005780 child = child->next;
5781 } else if (IS_SCHEMA(child, "documentation")) {
5782 /* TODO: make available the content of "documentation". */
5783 /*
5784 * source = anyURI
5785 * {any attributes with non-schema namespace . . .}>
5786 * Content: ({any})*
5787 */
5788 attr = child->properties;
5789 while (attr != NULL) {
5790 if (attr->ns == NULL) {
5791 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005792 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5794 NULL, NULL, attr);
5795 }
5796 } else {
5797 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5798 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5799 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005800
5801 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005802 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5803 NULL, NULL, attr);
5804 }
5805 }
5806 attr = attr->next;
5807 }
5808 /*
5809 * Attribute "xml:lang".
5810 */
5811 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5812 if (attr != NULL)
5813 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005814 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005815 child = child->next;
5816 } else {
5817 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005818 xmlSchemaPContentErr(ctxt,
5819 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005820 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5821 barked = 1;
5822 child = child->next;
5823 }
5824 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005825
Daniel Veillard4255d502002-04-16 15:50:10 +00005826 return (ret);
5827}
5828
5829/**
5830 * xmlSchemaParseFacet:
5831 * @ctxt: a schema validation context
5832 * @schema: the schema being built
5833 * @node: a subtree containing XML Schema informations
5834 *
5835 * parse a XML schema Facet declaration
5836 * *WARNING* this interface is highly subject to change
5837 *
5838 * Returns the new type structure or NULL in case of error
5839 */
5840static xmlSchemaFacetPtr
5841xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005842 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005843{
5844 xmlSchemaFacetPtr facet;
5845 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005846 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005847
5848 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5849 return (NULL);
5850
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005851 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005852 if (facet == NULL) {
5853 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5854 return (NULL);
5855 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005856 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005857 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005858 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005859 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5860 "Facet %s has no value\n", node->name, NULL);
5861 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005862 return (NULL);
5863 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005864 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005865 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005866 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005867 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005868 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005869 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005870 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005871 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005872 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005873 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005874 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005875 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005876 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005877 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005878 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005879 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005880 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005881 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005882 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005883 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005884 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005885 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5886 } else if (IS_SCHEMA(node, "minLength")) {
5887 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5888 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005889 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5890 "Unknown facet type %s\n", node->name, NULL);
5891 xmlSchemaFreeFacet(facet);
5892 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005893 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005894 xmlSchemaPValAttrID(ctxt, NULL,
5895 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005896 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005897 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5898 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5899 const xmlChar *fixed;
5900
5901 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5902 if (fixed != NULL) {
5903 if (xmlStrEqual(fixed, BAD_CAST "true"))
5904 facet->fixed = 1;
5905 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005906 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005907 child = node->children;
5908
5909 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005910 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5911 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005912 }
5913 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005914 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5915 "Facet %s has unexpected child content\n",
5916 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005917 }
5918 return (facet);
5919}
5920
5921/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005922 * xmlSchemaParseWildcardNs:
5923 * @ctxt: a schema parser context
5924 * @wildc: the wildcard, already created
5925 * @node: a subtree containing XML Schema informations
5926 *
5927 * Parses the attribute "processContents" and "namespace"
5928 * of a xsd:anyAttribute and xsd:any.
5929 * *WARNING* this interface is highly subject to change
5930 *
5931 * Returns 0 if everything goes fine, a positive error code
5932 * if something is not valid and -1 if an internal error occurs.
5933 */
5934static int
5935xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5936 xmlSchemaPtr schema,
5937 xmlSchemaWildcardPtr wildc,
5938 xmlNodePtr node)
5939{
5940 const xmlChar *pc, *ns, *dictnsItem;
5941 int ret = 0;
5942 xmlChar *nsItem;
5943 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5944 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005945
Daniel Veillardc0826a72004-08-10 14:17:33 +00005946 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5947 if ((pc == NULL)
5948 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5949 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5950 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5951 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5952 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5953 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5954 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005955 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005956 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005957 NULL, node,
5958 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005959 NULL, NULL, NULL);
5960 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005961 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005962 }
5963 /*
5964 * Build the namespace constraints.
5965 */
5966 attr = xmlSchemaGetPropNode(node, "namespace");
5967 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005968 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005969 wildc->any = 1;
5970 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5971 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005972 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005973 return (-1);
5974 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005975 wildc->negNsSet->value = schema->targetNamespace;
5976 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005977 const xmlChar *end, *cur;
5978
5979 cur = ns;
5980 do {
5981 while (IS_BLANK_CH(*cur))
5982 cur++;
5983 end = cur;
5984 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5985 end++;
5986 if (end == cur)
5987 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005988 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005989 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5990 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005991 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005992 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005993 NULL, (xmlNodePtr) attr,
5994 NULL,
5995 "((##any | ##other) | List of (xs:anyURI | "
5996 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005997 nsItem, NULL, NULL, NULL);
5998 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5999 } else {
6000 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6001 dictnsItem = schema->targetNamespace;
6002 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6003 dictnsItem = NULL;
6004 } else {
6005 /*
6006 * Validate the item (anyURI).
6007 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006008 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006009 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6010 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6011 }
6012 /*
6013 * Avoid dublicate namespaces.
6014 */
6015 tmp = wildc->nsSet;
6016 while (tmp != NULL) {
6017 if (dictnsItem == tmp->value)
6018 break;
6019 tmp = tmp->next;
6020 }
6021 if (tmp == NULL) {
6022 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6023 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006024 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006025 return (-1);
6026 }
6027 tmp->value = dictnsItem;
6028 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006029 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006030 wildc->nsSet = tmp;
6031 else
6032 lastNs->next = tmp;
6033 lastNs = tmp;
6034 }
6035
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006036 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006037 xmlFree(nsItem);
6038 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006039 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006040 }
6041 return (ret);
6042}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006043
6044static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006045xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6046 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006047 xmlNodePtr node,
6048 int minOccurs,
6049 int maxOccurs) {
6050
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006051 if ((maxOccurs == 0) && ( minOccurs == 0))
6052 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006053 if (maxOccurs != UNBOUNDED) {
6054 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006055 * TODO: Maybe we should better not create the particle,
6056 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006057 * content model.
6058 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006059 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006060 * 3.9.6 Schema Component Constraint: Particle Correct
6061 *
6062 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006063 if (maxOccurs < 1) {
6064 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006065 * 2.2 {max occurs} must be greater than or equal to 1.
6066 */
6067 xmlSchemaPCustomAttrErr(ctxt,
6068 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006069 NULL, NULL,
6070 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006071 "The value must be greater than or equal to 1");
6072 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6073 } else if (minOccurs > maxOccurs) {
6074 /*
6075 * 2.1 {min occurs} must not be greater than {max occurs}.
6076 */
6077 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006078 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006079 NULL, NULL,
6080 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006081 "The value must not be greater than the value of 'maxOccurs'");
6082 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6083 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006084 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006085 return (0);
6086}
6087
Daniel Veillardc0826a72004-08-10 14:17:33 +00006088/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006089 * xmlSchemaParseAny:
6090 * @ctxt: a schema validation context
6091 * @schema: the schema being built
6092 * @node: a subtree containing XML Schema informations
6093 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006094 * Parsea a XML schema <any> element. A particle and wildcard
6095 * will be created (except if minOccurs==maxOccurs==0, in this case
6096 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006097 * *WARNING* this interface is highly subject to change
6098 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006099 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006100 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006101static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006102xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6103 xmlNodePtr node)
6104{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006105 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006106 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006107 xmlSchemaWildcardPtr wild;
6108 int min, max;
6109 xmlAttrPtr attr;
6110 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006111
6112 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6113 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006114 /*
6115 * Check for illegal attributes.
6116 */
6117 attr = node->properties;
6118 while (attr != NULL) {
6119 if (attr->ns == NULL) {
6120 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6121 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6122 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6123 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6124 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006125 xmlSchemaPIllegalAttrErr(ctxt,
6126 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6127 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006128 }
6129 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006130 xmlSchemaPIllegalAttrErr(ctxt,
6131 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6132 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006133 }
6134 attr = attr->next;
6135 }
6136 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6137 /*
6138 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006139 */
6140 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6141 "(xs:nonNegativeInteger | unbounded)");
6142 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6143 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006144 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6145 /*
6146 * Create & parse the wildcard.
6147 */
6148 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6149 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006150 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006151 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006152 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006153 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006154 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006155 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006156 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006157 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006158 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006159 }
6160 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006161 xmlSchemaPContentErr(ctxt,
6162 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006163 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006164 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006165 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006166 /*
6167 * No component if minOccurs==maxOccurs==0.
6168 */
6169 if ((min == 0) && (max == 0)) {
6170 /* Don't free the wildcard, since it's already on the list. */
6171 return (NULL);
6172 }
6173 /*
6174 * Create the particle.
6175 */
6176 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6177 if (particle == NULL)
6178 return (NULL);
6179 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006180 wild->minOccurs = min;
6181 wild->maxOccurs = max;
6182 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006183
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006184 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006185}
6186
6187/**
6188 * xmlSchemaParseNotation:
6189 * @ctxt: a schema validation context
6190 * @schema: the schema being built
6191 * @node: a subtree containing XML Schema informations
6192 *
6193 * parse a XML schema Notation declaration
6194 *
6195 * Returns the new structure or NULL in case of error
6196 */
6197static xmlSchemaNotationPtr
6198xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006199 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006200{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006201 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 xmlSchemaNotationPtr ret;
6203 xmlNodePtr child = NULL;
6204
6205 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6206 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006207 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006208 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006209 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6210 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006211 return (NULL);
6212 }
6213 ret = xmlSchemaAddNotation(ctxt, schema, name);
6214 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006215 return (NULL);
6216 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006217 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006218
6219 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6220 node, BAD_CAST "id");
6221
6222 if (IS_SCHEMA(child, "annotation")) {
6223 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6224 child = child->next;
6225 }
6226
Daniel Veillard4255d502002-04-16 15:50:10 +00006227 child = node->children;
6228 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006229 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6230 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006231 }
6232 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006233 xmlSchemaPContentErr(ctxt,
6234 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006235 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006236 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006237 }
6238
6239 return (ret);
6240}
6241
6242/**
6243 * xmlSchemaParseAnyAttribute:
6244 * @ctxt: a schema validation context
6245 * @schema: the schema being built
6246 * @node: a subtree containing XML Schema informations
6247 *
6248 * parse a XML schema AnyAttrribute declaration
6249 * *WARNING* this interface is highly subject to change
6250 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006251 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006252 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006253static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006254xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6255 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006256{
Daniel Veillard3646d642004-06-02 19:19:14 +00006257 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006258 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006259 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006260
6261 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6262 return (NULL);
6263
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006264 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6265 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006266 if (ret == NULL) {
6267 return (NULL);
6268 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006269 /*
6270 * Check for illegal attributes.
6271 */
6272 attr = node->properties;
6273 while (attr != NULL) {
6274 if (attr->ns == NULL) {
6275 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6276 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6277 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006278 xmlSchemaPIllegalAttrErr(ctxt,
6279 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6280 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006281 }
6282 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006283 xmlSchemaPIllegalAttrErr(ctxt,
6284 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6285 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006286 }
6287 attr = attr->next;
6288 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006289 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6290 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006291 /*
6292 * Parse the namespace list.
6293 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006294 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006295 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006296 /*
6297 * And now for the children...
6298 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006299 child = node->children;
6300 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006301 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6302 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006303 }
6304 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006305 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006306 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006307 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006308 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006309 }
6310
6311 return (ret);
6312}
6313
6314
6315/**
6316 * xmlSchemaParseAttribute:
6317 * @ctxt: a schema validation context
6318 * @schema: the schema being built
6319 * @node: a subtree containing XML Schema informations
6320 *
6321 * parse a XML schema Attrribute declaration
6322 * *WARNING* this interface is highly subject to change
6323 *
William M. Bracke7091952004-05-11 15:09:58 +00006324 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006325 */
6326static xmlSchemaAttributePtr
6327xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006328 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006329{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006330 const xmlChar *name, *attrValue;
6331 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006332 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006333 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006334 xmlAttrPtr attr, nameAttr;
6335 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006336
6337 /*
6338 * Note that the w3c spec assumes the schema to be validated with schema
6339 * for schemas beforehand.
6340 *
6341 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006342 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006343
6344 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6345 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006346 attr = xmlSchemaGetPropNode(node, "ref");
6347 nameAttr = xmlSchemaGetPropNode(node, "name");
6348
6349 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006350 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006351 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006352 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006353 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006354 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6355 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006356 "One of the attributes 'ref' or 'name' must be present");
6357 return (NULL);
6358 }
6359 if ((topLevel) || (attr == NULL)) {
6360 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006361 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6362 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006363 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006364 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006365 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006366 isRef = 1;
6367
Daniel Veillardc0826a72004-08-10 14:17:33 +00006368 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006369 char buf[50];
6370 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006371
6372 /*
6373 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006374 */
6375 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6376 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6377 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006378 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006379 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006380 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006381 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006382 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006383 if (ret == NULL) {
6384 if (repName != NULL)
6385 xmlFree(repName);
6386 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006387 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006388 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6389 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006390 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006391 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006392 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6393 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006394 /*
6395 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6396 */
6397 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006398 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6399 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006400 "ref", "name");
6401 /*
6402 * Check for illegal attributes.
6403 */
6404 attr = node->properties;
6405 while (attr != NULL) {
6406 if (attr->ns == NULL) {
6407 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6408 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006409 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006410 * 3.2.3 : 3.2
6411 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006412 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006413 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006414 xmlSchemaPIllegalAttrErr(ctxt,
6415 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006416 (xmlSchemaTypePtr) ret, attr);
6417 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6418 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6419 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006420 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6421 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006422 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006423 xmlSchemaPIllegalAttrErr(ctxt,
6424 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6425 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006426 }
6427 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006428 xmlSchemaPIllegalAttrErr(ctxt,
6429 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6430 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006431 }
6432 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006433 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006434 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006435 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006436
Daniel Veillardc0826a72004-08-10 14:17:33 +00006437 /*
6438 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006439 */
6440 if (xmlSchemaPValAttrNode(ctxt,
6441 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006442 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6443 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006444 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006445 /*
6446 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6447 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006448 /*
6449 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6450 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006451 */
6452 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006453 xmlSchemaPSimpleTypeErr(ctxt,
6454 XML_SCHEMAP_NO_XMLNS,
6455 NULL, (xmlNodePtr) nameAttr,
6456 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6457 "The value of type 'xs:NCName' must not match 'xmlns'",
6458 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006459 if (repName != NULL)
6460 xmlFree(repName);
6461 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006462 }
6463 /*
6464 * Evaluate the target namespace
6465 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006466 if (topLevel) {
6467 ns = schema->targetNamespace;
6468 } else {
6469 attr = xmlSchemaGetPropNode(node, "form");
6470 if (attr != NULL) {
6471 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6472 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6473 ns = schema->targetNamespace;
6474 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006475 xmlSchemaPSimpleTypeErr(ctxt,
6476 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6477 NULL, (xmlNodePtr) attr,
6478 NULL, "(qualified | unqualified)",
6479 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006480 }
6481 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006482 ns = schema->targetNamespace;
6483 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006484 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006485 if (ret == NULL) {
6486 if (repName != NULL)
6487 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006488 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006489 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006490 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006491 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 if (topLevel)
6493 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006494 /*
6495 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6496 * TODO: Move this to the component layer.
6497 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006498 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006499 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006500 XML_SCHEMAP_NO_XSI,
6501 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006502 "The target namespace must not match '%s'",
6503 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006504 }
6505 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006506 * Check for illegal attributes.
6507 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006508 attr = node->properties;
6509 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006510 if (attr->ns == NULL) {
6511 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6512 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6513 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006514 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6515 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006516 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006517 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6518 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006519 xmlSchemaPIllegalAttrErr(ctxt,
6520 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6521 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006522 }
6523 }
6524 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006525 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6526 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006527 }
6528 attr = attr->next;
6529 }
6530 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006531 node, "type", &ret->typeNs, &ret->typeName);
6532 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006533 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6534 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006535 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006536 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006537 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006538 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6539 if (ret->defValue != NULL)
6540 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006541 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006542 * Attribute "default".
6543 */
6544 attr = xmlSchemaGetPropNode(node, "default");
6545 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 */
6550 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6551 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6552 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6553 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006554 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6555 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006556 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006557 /*
6558 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 */
6560 attr = xmlSchemaGetPropNode(node, "use");
6561 if (attr != NULL) {
6562 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6563 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6564 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6565 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6566 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6567 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6568 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6569 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006570 xmlSchemaPSimpleTypeErr(ctxt,
6571 XML_SCHEMAP_INVALID_ATTR_USE,
6572 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6573 NULL, "(optional | prohibited | required)",
6574 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006575 } else
6576 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006577 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006578 * 3.2.3 : 2
6579 * If default and use are both present, use must have
6580 * the actual value optional.
6581 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006582 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6583 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006584 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006585 xmlSchemaPSimpleTypeErr(ctxt,
6586 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6587 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6588 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006589 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006590 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006591 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006592 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006593 /*
6594 * And now for the children...
6595 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006596 child = node->children;
6597 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006598 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6599 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006600 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006601 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006602 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006603 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006604 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006605 * 3.2.3 : 3.2
6606 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006607 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006608 */
6609 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6610 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6611 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006612 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006613 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6614 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006615 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006616 }
6617 } else {
6618 if (IS_SCHEMA(child, "simpleType")) {
6619 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006620 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006621 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006622 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006623 */
6624 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6625 &repName, (xmlSchemaTypePtr) ret, node, child,
6626 "The attribute 'type' and the <simpleType> child "
6627 "are mutually exclusive", NULL);
6628 } else
6629 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6630 child = child->next;
6631 }
6632 if (child != NULL)
6633 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6634 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6635 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006636 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006637 /*
6638 * Cleanup.
6639 */
6640 if (repName != NULL)
6641 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006642 return (ret);
6643}
6644
6645/**
6646 * xmlSchemaParseAttributeGroup:
6647 * @ctxt: a schema validation context
6648 * @schema: the schema being built
6649 * @node: a subtree containing XML Schema informations
6650 *
6651 * parse a XML schema Attribute Group declaration
6652 * *WARNING* this interface is highly subject to change
6653 *
6654 * Returns the attribute group or NULL in case of error.
6655 */
6656static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006657xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006658 xmlSchemaPtr schema, xmlNodePtr node,
6659 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006660{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006661 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006662 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006663 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006664 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006665 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006666
6667 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6668 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006669
6670 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006671 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006672 if ((topLevel) || (attr == NULL)) {
6673 /*
6674 * Parse as an attribute group definition.
6675 * Note that those are allowed at top level only.
6676 */
6677 if (nameAttr == NULL) {
6678 xmlSchemaPMissingAttrErr(ctxt,
6679 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006680 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006681 return (NULL);
6682 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006683 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006684 * (xmlNodePtr) nameAttr);
6685 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006686 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006687 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006688 */
6689 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006690 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006691 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6692 return (NULL);
6693 }
6694 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6695 if (ret == NULL)
6696 return (NULL);
6697 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6698 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6699 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006700 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006701 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006702 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006703 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006704
6705 /*
6706 * Parse as an attribute group definition reference.
6707 */
6708 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006709 xmlSchemaPMissingAttrErr(ctxt,
6710 XML_SCHEMAP_S4S_ATTR_MISSING,
6711 NULL, node, "ref", NULL);
6712 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006713 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006714 NULL, NULL, attr, &refNs,&ref);
6715
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006716 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006717 name = (const xmlChar *) buf;
6718 if (name == NULL) {
6719 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6720 "attribute group definition reference", node);
6721 return (NULL);
6722 }
6723 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6724 if (ret == NULL)
6725 return (NULL);
6726 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6727 ret->ref = ref;
6728 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006729 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006730 xmlSchemaCheckReference(ctxt, schema, node,
6731 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006732 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006733 /*
6734 * Check for illegal attributes.
6735 */
6736 attr = node->properties;
6737 while (attr != NULL) {
6738 if (attr->ns == NULL) {
6739 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6740 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006741 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006742 {
6743 xmlSchemaPIllegalAttrErr(ctxt,
6744 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6745 NULL, NULL, attr);
6746 }
6747 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6748 xmlSchemaPIllegalAttrErr(ctxt,
6749 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6750 NULL, NULL, attr);
6751 }
6752 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006753 }
6754 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006755 /*
6756 * And now for the children...
6757 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006758 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006759 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006760 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006761 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006762 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6763 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006764 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006765 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006766 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006767 if (IS_SCHEMA(child, "anyAttribute")) {
6768 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6769 child = child->next;
6770 }
6771 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006772 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006773 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006774 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6775 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006776 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006777 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006778 ctxt->container = oldcontainer;
6779 return (ret);
6780}
6781
6782/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006783 * xmlSchemaPValAttrFormDefault:
6784 * @value: the value
6785 * @flags: the flags to be modified
6786 * @flagQualified: the specific flag for "qualified"
6787 *
6788 * Returns 0 if the value is valid, 1 otherwise.
6789 */
6790static int
6791xmlSchemaPValAttrFormDefault(const xmlChar *value,
6792 int *flags,
6793 int flagQualified)
6794{
6795 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6796 if ((*flags & flagQualified) == 0)
6797 *flags |= flagQualified;
6798 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006799 return (1);
6800
William M. Brack2f2a6632004-08-20 23:09:47 +00006801 return (0);
6802}
6803
6804/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006805 * xmlSchemaPValAttrBlockFinal:
6806 * @value: the value
6807 * @flags: the flags to be modified
6808 * @flagAll: the specific flag for "#all"
6809 * @flagExtension: the specific flag for "extension"
6810 * @flagRestriction: the specific flag for "restriction"
6811 * @flagSubstitution: the specific flag for "substitution"
6812 * @flagList: the specific flag for "list"
6813 * @flagUnion: the specific flag for "union"
6814 *
6815 * Validates the value of the attribute "final" and "block". The value
6816 * is converted into the specified flag values and returned in @flags.
6817 *
6818 * Returns 0 if the value is valid, 1 otherwise.
6819 */
6820
6821static int
6822xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006823 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006824 int flagAll,
6825 int flagExtension,
6826 int flagRestriction,
6827 int flagSubstitution,
6828 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006829 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006830{
6831 int ret = 0;
6832
6833 /*
6834 * TODO: This does not check for dublicate entries.
6835 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006836 if ((flags == NULL) || (value == NULL))
6837 return (-1);
6838 if (value[0] == 0)
6839 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006840 if (xmlStrEqual(value, BAD_CAST "#all")) {
6841 if (flagAll != -1)
6842 *flags |= flagAll;
6843 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006844 if (flagExtension != -1)
6845 *flags |= flagExtension;
6846 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006847 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006848 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006849 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006850 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006851 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006852 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006853 *flags |= flagUnion;
6854 }
6855 } else {
6856 const xmlChar *end, *cur = value;
6857 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006858
Daniel Veillardc0826a72004-08-10 14:17:33 +00006859 do {
6860 while (IS_BLANK_CH(*cur))
6861 cur++;
6862 end = cur;
6863 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6864 end++;
6865 if (end == cur)
6866 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006867 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006868 if (xmlStrEqual(item, BAD_CAST "extension")) {
6869 if (flagExtension != -1) {
6870 if ((*flags & flagExtension) == 0)
6871 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006872 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006873 ret = 1;
6874 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6875 if (flagRestriction != -1) {
6876 if ((*flags & flagRestriction) == 0)
6877 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006878 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006879 ret = 1;
6880 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6881 if (flagSubstitution != -1) {
6882 if ((*flags & flagSubstitution) == 0)
6883 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006884 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006885 ret = 1;
6886 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6887 if (flagList != -1) {
6888 if ((*flags & flagList) == 0)
6889 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006890 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006891 ret = 1;
6892 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6893 if (flagUnion != -1) {
6894 if ((*flags & flagUnion) == 0)
6895 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006896 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006897 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006898 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006899 ret = 1;
6900 if (item != NULL)
6901 xmlFree(item);
6902 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006903 } while ((ret == 0) && (*cur != 0));
6904 }
6905
Daniel Veillardc0826a72004-08-10 14:17:33 +00006906 return (ret);
6907}
6908
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006909static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006910xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006911 xmlSchemaIDCPtr idc,
6912 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006913 xmlAttrPtr attr,
6914 int isField)
6915{
6916 xmlNodePtr node;
6917
6918 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006919 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006920 * Schema Component Constraint: Selector Value OK
6921 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006922 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006923 * in [XPath].
6924 */
6925 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006926 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006927 XML_SCHEMAP_INTERNAL,
6928 "Internal error: xmlSchemaCheckCSelectorXPath, "
6929 "the selector is not specified.\n", NULL, NULL);
6930 return (-1);
6931 }
6932 if (attr == NULL)
6933 node = idc->node;
6934 else
6935 node = (xmlNodePtr) attr;
6936 if (selector->xpath == NULL) {
6937 xmlSchemaPCustomErr(ctxt,
6938 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006939 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6940 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006941 "The XPath expression of the selector is not valid", NULL);
6942 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6943 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006944 const xmlChar **nsArray = NULL;
6945 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006946 /*
6947 * Compile the XPath expression.
6948 */
6949 /*
6950 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006951 * TODO: Call xmlPatterncompile with different options for selector/
6952 * field.
6953 */
6954 nsList = xmlGetNsList(attr->doc, attr->parent);
6955 /*
6956 * Build an array of prefixes and namespaces.
6957 */
6958 if (nsList != NULL) {
6959 int i, count = 0;
6960 xmlNsPtr ns;
6961
6962 for (i = 0; nsList[i] != NULL; i++)
6963 count++;
6964
6965 nsArray = (const xmlChar **) xmlMalloc(
6966 (count * 2 + 1) * sizeof(const xmlChar *));
6967 if (nsArray == NULL) {
6968 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6969 NULL);
6970 return (-1);
6971 }
6972 for (i = 0; i < count; i++) {
6973 ns = nsList[i];
6974 nsArray[2 * i] = nsList[i]->href;
6975 nsArray[2 * i + 1] = nsList[i]->prefix;
6976 }
6977 nsArray[count * 2] = NULL;
6978 xmlFree(nsList);
6979 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006980 /*
6981 * TODO: Differentiate between "selector" and "field".
6982 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006983 if (isField)
6984 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006985 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006986 else
6987 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006988 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006989 if (nsArray != NULL)
6990 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006991
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006992 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006993 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006994 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006995 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6996 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006997 "The XPath expression '%s' could not be "
6998 "compiled", selector->xpath);
6999 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007000 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007001 }
7002 return (0);
7003}
7004
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007005#define ADD_ANNOTATION(annot) \
7006 xmlSchemaAnnotPtr cur = item->annot; \
7007 if (item->annot == NULL) { \
7008 item->annot = annot; \
7009 return (annot); \
7010 } \
7011 cur = item->annot; \
7012 if (cur->next != NULL) { \
7013 cur = cur->next; \
7014 } \
7015 cur->next = annot;
7016
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007017/**
7018 * xmlSchemaAssignAnnotation:
7019 * @item: the schema component
7020 * @annot: the annotation
7021 *
7022 * Adds the annotation to the given schema component.
7023 *
7024 * Returns the given annotaion.
7025 */
7026static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007027xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
7028 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007029{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007030 if ((annItem == NULL) || (annot == NULL))
7031 return (NULL);
7032 switch (annItem->type) {
7033 case XML_SCHEMA_TYPE_ELEMENT: {
7034 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
7035 ADD_ANNOTATION(annot)
7036 }
7037 break;
7038 case XML_SCHEMA_TYPE_ATTRIBUTE: {
7039 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
7040 ADD_ANNOTATION(annot)
7041 }
7042 break;
7043 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
7044 case XML_SCHEMA_TYPE_ANY: {
7045 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7046 ADD_ANNOTATION(annot)
7047 }
7048 break;
7049 case XML_SCHEMA_TYPE_PARTICLE:
7050 case XML_SCHEMA_TYPE_IDC_KEY:
7051 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007052 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007053 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7054 ADD_ANNOTATION(annot)
7055 }
7056 break;
7057 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7058 xmlSchemaAttributeGroupPtr item =
7059 (xmlSchemaAttributeGroupPtr) annItem;
7060 ADD_ANNOTATION(annot)
7061 }
7062 break;
7063 case XML_SCHEMA_TYPE_NOTATION: {
7064 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7065 ADD_ANNOTATION(annot)
7066 }
7067 break;
7068 case XML_SCHEMA_FACET_MININCLUSIVE:
7069 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7070 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7071 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7072 case XML_SCHEMA_FACET_TOTALDIGITS:
7073 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7074 case XML_SCHEMA_FACET_PATTERN:
7075 case XML_SCHEMA_FACET_ENUMERATION:
7076 case XML_SCHEMA_FACET_WHITESPACE:
7077 case XML_SCHEMA_FACET_LENGTH:
7078 case XML_SCHEMA_FACET_MAXLENGTH:
7079 case XML_SCHEMA_FACET_MINLENGTH: {
7080 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7081 ADD_ANNOTATION(annot)
7082 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007083 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007084 case XML_SCHEMA_TYPE_SIMPLE:
7085 case XML_SCHEMA_TYPE_COMPLEX: {
7086 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7087 ADD_ANNOTATION(annot)
7088 }
7089 break;
7090 case XML_SCHEMA_TYPE_GROUP: {
7091 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7092 ADD_ANNOTATION(annot)
7093 }
7094 break;
7095 case XML_SCHEMA_TYPE_SEQUENCE:
7096 case XML_SCHEMA_TYPE_CHOICE:
7097 case XML_SCHEMA_TYPE_ALL: {
7098 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7099 ADD_ANNOTATION(annot)
7100 }
7101 break;
7102 default:
7103 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007104 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007105 NULL, NULL, NULL,
7106 "Internal error: xmlSchemaAddAnnotation, "
7107 "The item is not a annotated schema component", NULL);
7108 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007109 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007110 return (annot);
7111}
7112
7113/**
7114 * xmlSchemaParseIDCSelectorAndField:
7115 * @ctxt: a schema validation context
7116 * @schema: the schema being built
7117 * @node: a subtree containing XML Schema informations
7118 *
7119 * Parses a XML Schema identity-contraint definition's
7120 * <selector> and <field> elements.
7121 *
7122 * Returns the parsed identity-constraint definition.
7123 */
7124static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007125xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007126 xmlSchemaPtr schema,
7127 xmlSchemaIDCPtr idc,
7128 xmlNodePtr node,
7129 int isField)
7130{
7131 xmlSchemaIDCSelectPtr item;
7132 xmlNodePtr child = NULL;
7133 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007134
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007135 /*
7136 * Check for illegal attributes.
7137 */
7138 attr = node->properties;
7139 while (attr != NULL) {
7140 if (attr->ns == NULL) {
7141 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7142 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007143 xmlSchemaPIllegalAttrErr(ctxt,
7144 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7145 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007146 }
7147 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007148 xmlSchemaPIllegalAttrErr(ctxt,
7149 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7150 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007151 }
7152 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007153 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007154 /*
7155 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007156 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007157 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7158 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007159 xmlSchemaPErrMemory(ctxt,
7160 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007161 NULL);
7162 return (NULL);
7163 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007164 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007165 /*
7166 * Attribute "xpath" (mandatory).
7167 */
7168 attr = xmlSchemaGetPropNode(node, "xpath");
7169 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007170 xmlSchemaPMissingAttrErr(ctxt,
7171 XML_SCHEMAP_S4S_ATTR_MISSING,
7172 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007173 "name", NULL);
7174 } else {
7175 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7176 /*
7177 * URGENT TODO: "field"s have an other syntax than "selector"s.
7178 */
7179
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007180 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7181 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007182 xmlSchemaPErr(ctxt,
7183 (xmlNodePtr) attr,
7184 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007185 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007186 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007187 NULL, NULL);
7188 }
7189
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007190 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007191 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007192 /*
7193 * And now for the children...
7194 */
7195 child = node->children;
7196 if (IS_SCHEMA(child, "annotation")) {
7197 /*
7198 * Add the annotation to the parent IDC.
7199 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007200 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007201 xmlSchemaParseAnnotation(ctxt, schema, child));
7202 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007203 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007204 if (child != NULL) {
7205 xmlSchemaPContentErr(ctxt,
7206 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007207 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007208 NULL, "(annotation?)");
7209 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007210
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007211 return (item);
7212}
7213
7214/**
7215 * xmlSchemaParseIDC:
7216 * @ctxt: a schema validation context
7217 * @schema: the schema being built
7218 * @node: a subtree containing XML Schema informations
7219 *
7220 * Parses a XML Schema identity-contraint definition.
7221 *
7222 * Returns the parsed identity-constraint definition.
7223 */
7224static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007225xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007226 xmlSchemaPtr schema,
7227 xmlNodePtr node,
7228 xmlSchemaTypeType idcCategory,
7229 const xmlChar *targetNamespace)
7230{
7231 xmlSchemaIDCPtr item = NULL;
7232 xmlNodePtr child = NULL;
7233 xmlAttrPtr attr;
7234 const xmlChar *name = NULL;
7235 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7236 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007237
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007238 /*
7239 * Check for illegal attributes.
7240 */
7241 attr = node->properties;
7242 while (attr != NULL) {
7243 if (attr->ns == NULL) {
7244 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7245 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7246 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7247 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007248 xmlSchemaPIllegalAttrErr(ctxt,
7249 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7250 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007251 }
7252 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007253 xmlSchemaPIllegalAttrErr(ctxt,
7254 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7255 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007256 }
7257 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007258 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007259 /*
7260 * Attribute "name" (mandatory).
7261 */
7262 attr = xmlSchemaGetPropNode(node, "name");
7263 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007264 xmlSchemaPMissingAttrErr(ctxt,
7265 XML_SCHEMAP_S4S_ATTR_MISSING,
7266 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007267 "name", NULL);
7268 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007269 } else if (xmlSchemaPValAttrNode(ctxt,
7270 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007271 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7272 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007273 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007274 /*
7275 * Create the component.
7276 */
7277 if (schema->idcDef == NULL)
7278 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007279 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007280 return (NULL);
7281
7282 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7283 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007284 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007285 "allocating an identity-constraint definition", NULL);
7286 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007287 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007288 /*
7289 * Add the IDC to the list of IDCs on the schema component.
7290 */
7291 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007292 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007293 xmlSchemaPCustomErrExt(ctxt,
7294 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007295 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007296 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007297 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007298 name, targetNamespace, NULL);
7299 xmlFree(item);
7300 return (NULL);
7301 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007302 memset(item, 0, sizeof(xmlSchemaIDC));
7303 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007304 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007305 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007306 if (ctxt->assemble != NULL)
7307 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007308 /*
7309 * The target namespace of the parent element declaration.
7310 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007311 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007312 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7313 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007314 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7315 /*
7316 * Attribute "refer" (mandatory).
7317 */
7318 attr = xmlSchemaGetPropNode(node, "refer");
7319 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007320 xmlSchemaPMissingAttrErr(ctxt,
7321 XML_SCHEMAP_S4S_ATTR_MISSING,
7322 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007323 "refer", NULL);
7324 } else {
7325 /*
7326 * Create a reference item.
7327 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007328 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007329 NULL, NULL);
7330 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007331 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007332 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007333 NULL, NULL, attr,
7334 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007335 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007336 xmlSchemaCheckReference(ctxt, schema, node,
7337 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007338 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007339 }
7340 }
7341 /*
7342 * And now for the children...
7343 */
7344 child = node->children;
7345 if (IS_SCHEMA(child, "annotation")) {
7346 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7347 child = child->next;
7348 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007349 if (child == NULL) {
7350 xmlSchemaPContentErr(ctxt,
7351 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007352 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007353 "A child element is missing",
7354 "(annotation?, (selector, field+))");
7355 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007356 /*
7357 * Child element <selector>.
7358 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007359 if (IS_SCHEMA(child, "selector")) {
7360 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007361 item, child, 0);
7362 child = child->next;
7363 /*
7364 * Child elements <field>.
7365 */
7366 if (IS_SCHEMA(child, "field")) {
7367 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007368 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007369 item, child, 1);
7370 if (field != NULL) {
7371 field->index = item->nbFields;
7372 item->nbFields++;
7373 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007374 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007375 else
7376 item->fields = field;
7377 lastField = field;
7378 }
7379 child = child->next;
7380 } while (IS_SCHEMA(child, "field"));
7381 } else {
7382 xmlSchemaPContentErr(ctxt,
7383 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007384 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007385 NULL, "(annotation?, (selector, field+))");
7386 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007387 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007388 if (child != NULL) {
7389 xmlSchemaPContentErr(ctxt,
7390 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007391 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007392 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007393 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007394
7395 return (item);
7396}
7397
Daniel Veillardc0826a72004-08-10 14:17:33 +00007398/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007399 * xmlSchemaParseElement:
7400 * @ctxt: a schema validation context
7401 * @schema: the schema being built
7402 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007403 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007404 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007405 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007406 * *WARNING* this interface is highly subject to change
7407 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007408 * Returns the element declaration or a particle; NULL in case
7409 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007410 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007411static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007412xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007413 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007414{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007415 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007416 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007417 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007418 xmlNodePtr child = NULL;
7419 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007420 int min, max, isRef = 0;
7421 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007422
7423 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7424 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007425
Daniel Veillard4255d502002-04-16 15:50:10 +00007426 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007427 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007428 /*
7429 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007430 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007431 * robust.
7432 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007433 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007434 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007435 if ((topLevel) || (attr == NULL)) {
7436 if (nameAttr == NULL) {
7437 xmlSchemaPMissingAttrErr(ctxt,
7438 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007439 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007440 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007441 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007442 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007443 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007444
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007445 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007446 child = node->children;
7447 if (IS_SCHEMA(child, "annotation")) {
7448 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7449 child = child->next;
7450 }
7451 /*
7452 * Skip particle part if a global declaration.
7453 */
7454 if (topLevel)
7455 goto declaration_part;
7456 /*
7457 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007458 */
7459 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7460 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7461 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007462 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7463 if (particle == NULL)
7464 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007465
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007466 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7467
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007468 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007469 const xmlChar *refNs = NULL, *ref = NULL;
7470 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007471 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007472 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007473 */
7474 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007475 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007476 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007477 /*
7478 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007479 */
7480 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007481 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007482 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007483 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007484 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007485 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007486 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007487 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007488 attr = node->properties;
7489 while (attr != NULL) {
7490 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007491 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7492 xmlStrEqual(attr->name, BAD_CAST "name") ||
7493 xmlStrEqual(attr->name, BAD_CAST "id") ||
7494 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7495 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7496 {
7497 attr = attr->next;
7498 continue;
7499 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007500 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007501 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007502 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007503 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007504 "Only the attributes 'minOccurs', 'maxOccurs' and "
7505 "'id' are allowed in addition to 'ref'");
7506 break;
7507 }
7508 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7509 xmlSchemaPIllegalAttrErr(ctxt,
7510 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007511 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007512 }
7513 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007514 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007515 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007516 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007517 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007518 if (child != NULL) {
7519 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7520 NULL, NULL, node, child, NULL, "(annotation?)");
7521 }
7522 if ((min == 0) && (max == 0))
7523 goto return_null;
7524 /*
7525 * Create the reference item.
7526 */
7527 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7528 ref, refNs);
7529 if (refer == NULL)
7530 goto return_null;
7531 particle->children = (xmlSchemaTreeItemPtr) refer;
7532 particle->annot = annot;
7533 /*
7534 * Add to assembled items; the reference need to be resolved.
7535 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007536 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007537 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7538
7539 return ((xmlSchemaBasicItemPtr) particle);
7540 }
7541 /*
7542 * The declaration part ===============================================
7543 */
7544declaration_part:
7545 {
7546 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7547 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7548
7549 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007550 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007551 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007552 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007553 * Evaluate the target namespace.
7554 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007555 if (topLevel) {
7556 ns = schema->targetNamespace;
7557 } else {
7558 attr = xmlSchemaGetPropNode(node, "form");
7559 if (attr != NULL) {
7560 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7561 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007562 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007563 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007564 xmlSchemaPSimpleTypeErr(ctxt,
7565 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7566 NULL, (xmlNodePtr) attr,
7567 NULL, "(qualified | unqualified)",
7568 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007569 }
7570 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007571 ns = schema->targetNamespace;
7572 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007573 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007574 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007575 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007576 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007577 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7578 decl->node = node;
7579 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007580 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007581 * Check for illegal attributes.
7582 */
William M. Bracke7091952004-05-11 15:09:58 +00007583 attr = node->properties;
7584 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007585 if (attr->ns == NULL) {
7586 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7587 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007588 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007589 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007590 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007591 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007592 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7593 {
7594 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007595 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007596 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007597 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007598 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007599 xmlSchemaPIllegalAttrErr(ctxt,
7600 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7601 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007602 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007603 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7604 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007605 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7606
7607 xmlSchemaPIllegalAttrErr(ctxt,
7608 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007609 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007610 }
7611 }
7612 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007613
Daniel Veillardc0826a72004-08-10 14:17:33 +00007614 xmlSchemaPIllegalAttrErr(ctxt,
7615 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007616 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007617 }
7618 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007619 }
William M. Bracke7091952004-05-11 15:09:58 +00007620 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007621 * Extract/validate attributes.
7622 */
7623 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007624 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007625 * Process top attributes of global element declarations here.
7626 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007627 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7628 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007629 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7630 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7631 &(decl->substGroupNs), &(decl->substGroup));
7632 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007633 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007634 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007635 /*
7636 * Attribute "final".
7637 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007638 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007639 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007640 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7641 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7642 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7643 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007644 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007645 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7646 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007647 -1,
7648 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7649 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007650 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007651 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007652 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7653 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007654 attrValue, NULL, NULL, NULL);
7655 }
7656 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007657 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007658 /*
7659 * Attribute "block".
7660 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007661 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007662 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007663 /*
7664 * Apply default "block" values.
7665 */
7666 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7667 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7668 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7669 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7670 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7671 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007672 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007673 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7674 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007675 -1,
7676 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007677 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007678 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7679 xmlSchemaPSimpleTypeErr(ctxt,
7680 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007681 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007682 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007683 "restriction | substitution))", attrValue,
7684 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007685 }
7686 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007687 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007689 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007690
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007691 attr = xmlSchemaGetPropNode(node, "type");
7692 if (attr != NULL) {
7693 xmlSchemaPValAttrNodeQName(ctxt, schema,
7694 NULL, (xmlSchemaTypePtr) decl, attr,
7695 &(decl->namedTypeNs), &(decl->namedType));
7696 xmlSchemaCheckReference(ctxt, schema, node,
7697 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7698 }
7699 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7700 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007701 if (attr != NULL) {
7702 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007703 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007704 /*
7705 * 3.3.3 : 1
7706 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007707 */
7708 xmlSchemaPMutualExclAttrErr(ctxt,
7709 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007710 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007711 "default", "fixed");
7712 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007713 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7714 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007715 }
William M. Bracke7091952004-05-11 15:09:58 +00007716 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007717 /*
7718 * And now for the children...
7719 */
7720 oldcontainer = ctxt->container;
7721 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007722 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007723 /*
7724 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007725 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007726 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007727 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007728 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007729 xmlSchemaPContentErr(ctxt,
7730 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007731 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007732 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007733 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007734 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007735 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007736 child = child->next;
7737 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007738 /*
7739 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007740 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007741 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007742 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007743 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007744 xmlSchemaPContentErr(ctxt,
7745 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007746 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007747 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007748 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007749 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007750 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007751 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007752 }
William M. Bracke7091952004-05-11 15:09:58 +00007753 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007754 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007755 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007756 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007757 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007758 } else if (IS_SCHEMA(child, "key")) {
7759 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007760 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007761 } else if (IS_SCHEMA(child, "keyref")) {
7762 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007763 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007764 }
7765 if (lastIDC != NULL)
7766 lastIDC->next = curIDC;
7767 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007768 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007769 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007770 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007771 }
7772 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007773 xmlSchemaPContentErr(ctxt,
7774 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007775 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007776 NULL, "(annotation?, ((simpleType | complexType)?, "
7777 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007778 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007779 ctxt->container = oldcontainer;
7780 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007781 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007782 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007783 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007784 * different layer.
7785 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007786 FREE_AND_NULL(des)
7787 if (topLevel)
7788 return ((xmlSchemaBasicItemPtr) decl);
7789 else {
7790 particle->children = (xmlSchemaTreeItemPtr) decl;
7791 return ((xmlSchemaBasicItemPtr) particle);
7792 }
7793
7794return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007795 FREE_AND_NULL(des);
7796 if (annot != NULL) {
7797 if (particle != NULL)
7798 particle->annot = NULL;
7799 if (decl != NULL)
7800 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007801 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007802 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007803 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007804}
7805
7806/**
7807 * xmlSchemaParseUnion:
7808 * @ctxt: a schema validation context
7809 * @schema: the schema being built
7810 * @node: a subtree containing XML Schema informations
7811 *
7812 * parse a XML schema Union definition
7813 * *WARNING* this interface is highly subject to change
7814 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007815 * Returns -1 in case of internal error, 0 in case of success and a positive
7816 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007817 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007818static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007819xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007820 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007821{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007822 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007823 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007824 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007825 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007826
7827 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007828 return (-1);
7829 /* Not a component, don't create it. */
7830 type = ctxt->ctxtType;
7831 /*
7832 * Mark the simple type as being of variety "union".
7833 */
7834 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007835 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007836 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7837 * then the ·simple ur-type definition·."
7838 */
7839 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007840 /*
7841 * Check for illegal attributes.
7842 */
7843 attr = node->properties;
7844 while (attr != NULL) {
7845 if (attr->ns == NULL) {
7846 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7847 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007848 xmlSchemaPIllegalAttrErr(ctxt,
7849 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7850 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007851 }
7852 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007853 xmlSchemaPIllegalAttrErr(ctxt,
7854 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7855 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007856 }
7857 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007858 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007859 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007860 /*
7861 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007862 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007863 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007864 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007865 if (attr != NULL) {
7866 const xmlChar *end;
7867 xmlChar *tmp;
7868 const xmlChar *localName, *nsName;
7869 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7870 xmlSchemaQNameRefPtr ref;
7871
7872 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007873 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007874 do {
7875 while (IS_BLANK_CH(*cur))
7876 cur++;
7877 end = cur;
7878 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7879 end++;
7880 if (end == cur)
7881 break;
7882 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007883 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7884 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007885 /*
7886 * Create the member type link.
7887 */
7888 link = (xmlSchemaTypeLinkPtr)
7889 xmlMalloc(sizeof(xmlSchemaTypeLink));
7890 if (link == NULL) {
7891 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7892 "allocating a type link", NULL);
7893 return (-1);
7894 }
7895 link->type = NULL;
7896 link->next = NULL;
7897 if (lastLink == NULL)
7898 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007899 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007900 lastLink->next = link;
7901 lastLink = link;
7902 /*
7903 * Create a reference item.
7904 */
7905 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7906 localName, nsName);
7907 if (ref == NULL) {
7908 FREE_AND_NULL(tmp)
7909 return (-1);
7910 }
7911 /*
7912 * Assign the reference to the link, it will be resolved
7913 * later during fixup of the union simple type.
7914 */
7915 link->type = (xmlSchemaTypePtr) ref;
7916 }
7917 FREE_AND_NULL(tmp)
7918 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007919 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007920
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007921 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007922 /*
7923 * And now for the children...
7924 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007925 child = node->children;
7926 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007927 /*
7928 * Add the annotation to the simple type ancestor.
7929 */
7930 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7931 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007932 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007933 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007934 if (IS_SCHEMA(child, "simpleType")) {
7935 xmlSchemaTypePtr subtype, last = NULL;
7936
7937 /*
7938 * Anchor the member types in the "subtypes" field of the
7939 * simple type.
7940 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007941 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007942 subtype = (xmlSchemaTypePtr)
7943 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7944 if (subtype != NULL) {
7945 if (last == NULL) {
7946 type->subtypes = subtype;
7947 last = subtype;
7948 } else {
7949 last->next = subtype;
7950 last = subtype;
7951 }
7952 last->next = NULL;
7953 }
7954 child = child->next;
7955 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007956 }
7957 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007958 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007959 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007960 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007961 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007962 if ((attr == NULL) && (type->subtypes == NULL)) {
7963 /*
7964 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007965 * Either the memberTypes [attribute] of the <union> element must
7966 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007967 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007968 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007969 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7970 NULL, NULL, node,
7971 "Either the attribute 'memberTypes' or "
7972 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007973 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007974 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007975}
7976
7977/**
7978 * xmlSchemaParseList:
7979 * @ctxt: a schema validation context
7980 * @schema: the schema being built
7981 * @node: a subtree containing XML Schema informations
7982 *
7983 * parse a XML schema List definition
7984 * *WARNING* this interface is highly subject to change
7985 *
William M. Bracke7091952004-05-11 15:09:58 +00007986 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007987 * 1 in case of success.
7988 */
7989static xmlSchemaTypePtr
7990xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007991 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007992{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007993 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007994 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007995 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007996
7997 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7998 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007999 /* Not a component, don't create it. */
8000 type = ctxt->ctxtType;
8001 /*
8002 * Mark the type as being of variety "list".
8003 */
8004 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008005 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008006 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8007 * then the ·simple ur-type definition·."
8008 */
8009 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008010 /*
8011 * Check for illegal attributes.
8012 */
8013 attr = node->properties;
8014 while (attr != NULL) {
8015 if (attr->ns == NULL) {
8016 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8017 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008018 xmlSchemaPIllegalAttrErr(ctxt,
8019 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8020 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008021 }
8022 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008023 xmlSchemaPIllegalAttrErr(ctxt,
8024 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8025 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008026 }
8027 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008028 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008029
8030 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8031
William M. Brack2f2a6632004-08-20 23:09:47 +00008032 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008033 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
8034 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00008035 */
8036 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008037 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00008038 /*
8039 * And now for the children...
8040 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008041 child = node->children;
8042 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008043 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8044 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008045 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008046 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008047 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008048 /*
8049 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008050 * Either the itemType [attribute] or the <simpleType> [child] of
8051 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008052 */
8053 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008054 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008055 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008056 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008057 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008058 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008059 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008060 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008061 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008062 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008063 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008064 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008065 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008066 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008067 "Either the attribute 'itemType' or the <simpleType> child "
8068 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008069 }
8070 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008071 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008072 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008073 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008074 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008075 if ((type->ref == NULL) &&
8076 (type->subtypes == NULL) &&
8077 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008078 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008079 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008080 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008081 "Either the attribute 'itemType' or the <simpleType> child "
8082 "must be present", NULL);
8083 }
8084 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008085}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008086
Daniel Veillard4255d502002-04-16 15:50:10 +00008087/**
8088 * xmlSchemaParseSimpleType:
8089 * @ctxt: a schema validation context
8090 * @schema: the schema being built
8091 * @node: a subtree containing XML Schema informations
8092 *
8093 * parse a XML schema Simple Type definition
8094 * *WARNING* this interface is highly subject to change
8095 *
William M. Bracke7091952004-05-11 15:09:58 +00008096 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008097 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008098 */
8099static xmlSchemaTypePtr
8100xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008101 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008102{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008103 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008104 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008105 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008106 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008107
8108 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8109 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008110
Daniel Veillardc0826a72004-08-10 14:17:33 +00008111 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008112 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008113 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008114 xmlSchemaPMissingAttrErr(ctxt,
8115 XML_SCHEMAP_S4S_ATTR_MISSING,
8116 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008117 "name", NULL);
8118 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008119 } else {
8120 if (xmlSchemaPValAttrNode(ctxt,
8121 NULL, NULL, attr,
8122 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8123 return (NULL);
8124 /*
8125 * Skip built-in types.
8126 */
8127 if (ctxt->isS4S) {
8128 xmlSchemaTypePtr biType;
8129
8130 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8131 if (biType != NULL)
8132 return (biType);
8133 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008134 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008135 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008136
Daniel Veillardc0826a72004-08-10 14:17:33 +00008137 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008138 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008139
Daniel Veillard01fa6152004-06-29 17:04:39 +00008140 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008141 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008142 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008143 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008144 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008145 if (type == NULL)
8146 return (NULL);
8147 type->node = node;
8148 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008149 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008150 /*
8151 * Check for illegal attributes.
8152 */
8153 attr = node->properties;
8154 while (attr != NULL) {
8155 if (attr->ns == NULL) {
8156 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008157 xmlSchemaPIllegalAttrErr(ctxt,
8158 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8159 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008160 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008161 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008162 xmlSchemaPIllegalAttrErr(ctxt,
8163 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8164 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008165 }
8166 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008167 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008168 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008169 /*
8170 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008171 *
8172 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008173 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008174 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008175 if (type == NULL)
8176 return (NULL);
8177 type->node = node;
8178 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008179 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008180 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8181 /*
8182 * Check for illegal attributes.
8183 */
8184 attr = node->properties;
8185 while (attr != NULL) {
8186 if (attr->ns == NULL) {
8187 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8188 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008189 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008190 xmlSchemaPIllegalAttrErr(ctxt,
8191 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8192 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008193 }
8194 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008195 xmlSchemaPIllegalAttrErr(ctxt,
8196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8197 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008198 }
8199 attr = attr->next;
8200 }
8201 /*
8202 * Attribute "final".
8203 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008204 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008205 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008206 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8207 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8208 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8209 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8210 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8211 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008212 } else {
8213 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008214 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8215 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008216 XML_SCHEMAS_TYPE_FINAL_LIST,
8217 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8218
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008219 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008220 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008221 type, (xmlNodePtr) attr,
8222 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008223 attrValue, NULL, NULL, NULL);
8224 }
8225 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008226 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008227 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008228 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008229 /*
8230 * And now for the children...
8231 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008232 oldCtxtType = ctxt->ctxtType;
8233 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008234 ctxt->ctxtType = type;
8235 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008236 child = node->children;
8237 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008238 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8239 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008240 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008241 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008242 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8243 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008244 "(annotation?, (restriction | list | union))");
8245 } else if (IS_SCHEMA(child, "restriction")) {
8246 xmlSchemaParseRestriction(ctxt, schema, child,
8247 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008248 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008249 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008250 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008251 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008252 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008253 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008254 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008255 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008256 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008257 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8258 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008259 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008260 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008261 ctxt->parentItem = oldParentItem;
8262 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008263
Daniel Veillard4255d502002-04-16 15:50:10 +00008264 return (type);
8265}
8266
Daniel Veillard4255d502002-04-16 15:50:10 +00008267/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008268 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008269 * @ctxt: a schema validation context
8270 * @schema: the schema being built
8271 * @node: a subtree containing XML Schema informations
8272 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008273 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008274 * *WARNING* this interface is highly subject to change
8275 *
William M. Bracke7091952004-05-11 15:09:58 +00008276 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008277 * 1 in case of success.
8278 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008279static xmlSchemaTreeItemPtr
8280xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8281 xmlSchemaPtr schema,
8282 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008283{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008284 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008285 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008286 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008287 const xmlChar *ref = NULL, *refNs = NULL;
8288 int min, max;
8289
8290 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008291 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008292
8293 attr = xmlSchemaGetPropNode(node, "ref");
8294 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008295 xmlSchemaPMissingAttrErr(ctxt,
8296 XML_SCHEMAP_S4S_ATTR_MISSING,
8297 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008298 "ref", NULL);
8299 return (NULL);
8300 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008301 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008302 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008303 }
8304 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008305 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008306 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008307 /*
8308 * Check for illegal attributes.
8309 */
8310 attr = node->properties;
8311 while (attr != NULL) {
8312 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008313 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008314 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8315 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8316 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008317 xmlSchemaPIllegalAttrErr(ctxt,
8318 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8319 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008320 }
8321 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008322 xmlSchemaPIllegalAttrErr(ctxt,
8323 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8324 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008325 }
8326 attr = attr->next;
8327 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008328 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008329 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8330 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008331 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008332 /*
8333 * Create a reference item as the term; it will be substituted for
8334 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008335 */
8336 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008337 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8338 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8339 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8340 /*
8341 * And now for the children...
8342 */
8343 child = node->children;
8344 /* TODO: Is annotation even allowed for a model group reference? */
8345 if (IS_SCHEMA(child, "annotation")) {
8346 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008347 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008348 */
8349 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8350 child = child->next;
8351 }
8352 if (child != NULL) {
8353 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008354 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008355 NULL, NULL, node, child, NULL,
8356 "(annotation?)");
8357 }
8358 /*
8359 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8360 */
8361 if ((min == 0) && (max == 0))
8362 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008363 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008364 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8365 return ((xmlSchemaTreeItemPtr) item);
8366}
8367
8368/**
8369 * xmlSchemaParseModelGroupDefinition:
8370 * @ctxt: a schema validation context
8371 * @schema: the schema being built
8372 * @node: a subtree containing XML Schema informations
8373 *
8374 * Parses a XML schema model group definition.
8375 * *WARNING* this interface is highly subject to change
8376 *
8377 * Returns -1 in case of error, 0 if the declaration is improper and
8378 * 1 in case of success.
8379 */
8380static xmlSchemaModelGroupDefPtr
8381xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8382 xmlSchemaPtr schema,
8383 xmlNodePtr node)
8384{
8385 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008386 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008387 xmlAttrPtr attr;
8388 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008389
8390 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008391 return (NULL);
8392
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008393 attr = xmlSchemaGetPropNode(node, "name");
8394 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008395 xmlSchemaPMissingAttrErr(ctxt,
8396 XML_SCHEMAP_S4S_ATTR_MISSING,
8397 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008398 "name", NULL);
8399 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008400 } else if (xmlSchemaPValAttrNode(ctxt,
8401 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008402 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8403 return (NULL);
8404 }
8405 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8406 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008407 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008408 /*
8409 * Check for illegal attributes.
8410 */
8411 attr = node->properties;
8412 while (attr != NULL) {
8413 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008414 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008415 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008416 xmlSchemaPIllegalAttrErr(ctxt,
8417 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8418 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008419 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008420 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008421 xmlSchemaPIllegalAttrErr(ctxt,
8422 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8423 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008424 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008425 attr = attr->next;
8426 }
8427 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8428 /*
8429 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008430 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008431 child = node->children;
8432 if (IS_SCHEMA(child, "annotation")) {
8433 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8434 child = child->next;
8435 }
8436 if (IS_SCHEMA(child, "all")) {
8437 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8438 XML_SCHEMA_TYPE_ALL, 0);
8439 child = child->next;
8440 } else if (IS_SCHEMA(child, "choice")) {
8441 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8442 XML_SCHEMA_TYPE_CHOICE, 0);
8443 child = child->next;
8444 } else if (IS_SCHEMA(child, "sequence")) {
8445 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8446 XML_SCHEMA_TYPE_SEQUENCE, 0);
8447 child = child->next;
8448 }
8449 if (child != NULL) {
8450 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008451 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8452 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008453 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008454 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008455
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008456 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008457}
8458
8459/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008460 * xmlSchemaCleanupDoc:
8461 * @ctxt: a schema validation context
8462 * @node: the root of the document.
8463 *
8464 * removes unwanted nodes in a schemas document tree
8465 */
8466static void
8467xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8468{
8469 xmlNodePtr delete, cur;
8470
8471 if ((ctxt == NULL) || (root == NULL)) return;
8472
8473 /*
8474 * Remove all the blank text nodes
8475 */
8476 delete = NULL;
8477 cur = root;
8478 while (cur != NULL) {
8479 if (delete != NULL) {
8480 xmlUnlinkNode(delete);
8481 xmlFreeNode(delete);
8482 delete = NULL;
8483 }
8484 if (cur->type == XML_TEXT_NODE) {
8485 if (IS_BLANK_NODE(cur)) {
8486 if (xmlNodeGetSpacePreserve(cur) != 1) {
8487 delete = cur;
8488 }
8489 }
8490 } else if ((cur->type != XML_ELEMENT_NODE) &&
8491 (cur->type != XML_CDATA_SECTION_NODE)) {
8492 delete = cur;
8493 goto skip_children;
8494 }
8495
8496 /*
8497 * Skip to next node
8498 */
8499 if (cur->children != NULL) {
8500 if ((cur->children->type != XML_ENTITY_DECL) &&
8501 (cur->children->type != XML_ENTITY_REF_NODE) &&
8502 (cur->children->type != XML_ENTITY_NODE)) {
8503 cur = cur->children;
8504 continue;
8505 }
8506 }
8507 skip_children:
8508 if (cur->next != NULL) {
8509 cur = cur->next;
8510 continue;
8511 }
8512
8513 do {
8514 cur = cur->parent;
8515 if (cur == NULL)
8516 break;
8517 if (cur == root) {
8518 cur = NULL;
8519 break;
8520 }
8521 if (cur->next != NULL) {
8522 cur = cur->next;
8523 break;
8524 }
8525 } while (cur != NULL);
8526 }
8527 if (delete != NULL) {
8528 xmlUnlinkNode(delete);
8529 xmlFreeNode(delete);
8530 delete = NULL;
8531 }
8532}
8533
William M. Brack2f2a6632004-08-20 23:09:47 +00008534
8535/**
8536 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008537 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008538 * @ctxt: a schema validation context
8539 * @schemaLocation: an URI defining where to find the imported schema
8540 *
8541 * import a XML schema
8542 * *WARNING* this interface is highly subject to change
8543 *
8544 * Returns -1 in case of error and 1 in case of success.
8545 */
8546#if 0
8547static xmlSchemaImportPtr
8548xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8549 const xmlChar *schemaLocation)
8550{
8551 xmlSchemaImportPtr import;
8552 xmlSchemaParserCtxtPtr newctxt;
8553
8554 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8555 if (newctxt == NULL) {
8556 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8557 NULL);
8558 return (NULL);
8559 }
8560 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8561 /* Keep the same dictionnary for parsing, really */
8562 xmlDictReference(ctxt->dict);
8563 newctxt->dict = ctxt->dict;
8564 newctxt->includes = 0;
8565 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8566
8567 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8568 ctxt->userData);
8569
8570 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8571 if (import == NULL) {
8572 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8573 NULL);
8574 xmlSchemaFreeParserCtxt(newctxt);
8575 return (NULL);
8576 }
8577
8578 memset(import, 0, sizeof(xmlSchemaImport));
8579 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8580 import->schema = xmlSchemaParse(newctxt);
8581
8582 if (import->schema == NULL) {
8583 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008584 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008585 "Failed to import schema from location \"%s\".\n",
8586 schemaLocation, NULL);
8587
8588 xmlSchemaFreeParserCtxt(newctxt);
8589 /* The schemaLocation is held by the dictionary.
8590 if (import->schemaLocation != NULL)
8591 xmlFree((xmlChar *)import->schemaLocation);
8592 */
8593 xmlFree(import);
8594 return NULL;
8595 }
8596
8597 xmlSchemaFreeParserCtxt(newctxt);
8598 return import;
8599}
8600#endif
8601
8602static void
8603xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8604{
8605 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8606 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8607
8608 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8609 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8610
8611 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8612 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8613 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8614 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8615 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8616 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8617 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8618 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8619
8620 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8621 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8622 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8623 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8624 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8625 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8626}
8627
8628static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008629xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008630 xmlSchemaPtr schema,
8631 xmlNodePtr node)
8632{
8633 xmlAttrPtr attr;
8634 const xmlChar *val;
8635
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008636 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8637 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008639 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8640 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008641 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008642 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8643
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008644 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008645 if (attr != NULL) {
8646 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008647 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008648 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008649 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008650 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008651 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008652 "(qualified | unqualified)", val, NULL, NULL, NULL);
8653 }
8654 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008655
8656 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008657 if (attr != NULL) {
8658 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008659 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008660 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008661 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008662 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008663 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008664 "(qualified | unqualified)", val, NULL, NULL, NULL);
8665 }
8666 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008667
8668 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008669 if (attr != NULL) {
8670 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8671 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8672 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8673 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8674 -1,
8675 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8676 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8677 xmlSchemaPSimpleTypeErr(ctxt,
8678 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008679 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008680 "(#all | List of (extension | restriction | list | union))",
8681 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008682 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008683 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008684
8685 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008686 if (attr != NULL) {
8687 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8688 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8689 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8690 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8691 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8692 xmlSchemaPSimpleTypeErr(ctxt,
8693 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008694 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008695 "(#all | List of (extension | restriction | substitution))",
8696 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008697 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008698 }
8699}
8700
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008701/**
8702 * xmlSchemaParseSchemaTopLevel:
8703 * @ctxt: a schema validation context
8704 * @schema: the schemas
8705 * @nodes: the list of top level nodes
8706 *
8707 * Returns the internal XML Schema structure built from the resource or
8708 * NULL in case of error
8709 */
8710static void
8711xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8712 xmlSchemaPtr schema, xmlNodePtr nodes)
8713{
8714 xmlNodePtr child;
8715 xmlSchemaAnnotPtr annot;
8716
8717 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8718 return;
8719
8720 child = nodes;
8721 while ((IS_SCHEMA(child, "include")) ||
8722 (IS_SCHEMA(child, "import")) ||
8723 (IS_SCHEMA(child, "redefine")) ||
8724 (IS_SCHEMA(child, "annotation"))) {
8725 if (IS_SCHEMA(child, "annotation")) {
8726 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8727 if (schema->annot == NULL)
8728 schema->annot = annot;
8729 else
8730 xmlSchemaFreeAnnot(annot);
8731 } else if (IS_SCHEMA(child, "import")) {
8732 xmlSchemaParseImport(ctxt, schema, child);
8733 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008734 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008735 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008736 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008737 } else if (IS_SCHEMA(child, "redefine")) {
8738 TODO
8739 }
8740 child = child->next;
8741 }
8742 while (child != NULL) {
8743 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008744 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008745 child = child->next;
8746 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008747 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008748 child = child->next;
8749 } else if (IS_SCHEMA(child, "element")) {
8750 xmlSchemaParseElement(ctxt, schema, child, 1);
8751 child = child->next;
8752 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008753 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008754 child = child->next;
8755 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008756 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008757 child = child->next;
8758 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008759 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008760 child = child->next;
8761 } else if (IS_SCHEMA(child, "notation")) {
8762 xmlSchemaParseNotation(ctxt, schema, child);
8763 child = child->next;
8764 } else {
8765 xmlSchemaPErr2(ctxt, NULL, child,
8766 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008767 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008768 child->name, NULL);
8769 child = child->next;
8770 }
8771 while (IS_SCHEMA(child, "annotation")) {
8772 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8773 if (schema->annot == NULL)
8774 schema->annot = annot;
8775 else
8776 xmlSchemaFreeAnnot(annot);
8777 child = child->next;
8778 }
8779 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008780 ctxt->parentItem = NULL;
8781 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008782}
8783
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008784static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008785xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008786 xmlHashTablePtr *imports,
8787 const xmlChar *nsName)
8788{
8789 xmlSchemaImportPtr ret;
8790
8791 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008792 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008793 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008794 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008795 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8796 NULL, NULL, (xmlNodePtr) ctxt->doc,
8797 "Internal error: failed to build the import table",
8798 NULL);
8799 return (NULL);
8800 }
8801 }
8802 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8803 if (ret == NULL) {
8804 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8805 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008806 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008807 memset(ret, 0, sizeof(xmlSchemaImport));
8808 if (nsName == NULL)
8809 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008810 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008811
8812 return (ret);
8813}
8814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008815/**
8816 * xmlSchemaNewParserCtxtUseDict:
8817 * @URL: the location of the schema
8818 * @dict: the dictionary to be used
8819 *
8820 * Create an XML Schemas parse context for that file/resource expected
8821 * to contain an XML Schemas file.
8822 *
8823 * Returns the parser context or NULL in case of error
8824 */
8825static xmlSchemaParserCtxtPtr
8826xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8827{
8828 xmlSchemaParserCtxtPtr ret;
8829 /*
8830 if (URL == NULL)
8831 return (NULL);
8832 */
8833
8834 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8835 if (ret == NULL) {
8836 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8837 NULL);
8838 return (NULL);
8839 }
8840 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8841 ret->dict = dict;
8842 xmlDictReference(dict);
8843 if (URL != NULL)
8844 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8845 ret->includes = 0;
8846 return (ret);
8847}
8848
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008849static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008850xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8851{
8852 if (vctxt->pctxt == NULL) {
8853 if (vctxt->schema != NULL)
8854 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8855 else
8856 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8857 if (vctxt->pctxt == NULL) {
8858 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8859 "failed to create a temp. parser context");
8860 return (-1);
8861 }
8862 /* TODO: Pass user data. */
8863 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8864 }
8865 return (0);
8866}
8867
8868static int
8869xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008870 xmlSchemaPtr schema,
8871 xmlNodePtr node,
8872 const xmlChar *nsName,
8873 const xmlChar *location,
8874 xmlDocPtr *doc,
8875 const xmlChar **targetNamespace,
8876 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008877{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008878 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008879 xmlParserCtxtPtr parserCtxt;
8880 xmlSchemaImportPtr import;
8881 const xmlChar *ns;
8882 xmlNodePtr root;
8883
8884 /*
8885 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8886 * <xsi:noNamespaceSchemaLocation>.
8887 */
8888 *doc = NULL;
8889 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008890 * Given that the schemaLocation [attribute] is only a hint, it is open
8891 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008892 * namespace, regardless of the ·actual value· of schemaLocation, but
8893 * such a strategy risks missing useful information when new
8894 * schemaLocations are offered.
8895 *
8896 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8897 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8898 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008899 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008900 */
8901 if (location == NULL) {
8902 /*
8903 * Schema Document Location Strategy:
8904 *
8905 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008906 * either as a resource which is an XML document or a <schema> element
8907 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008908 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008909 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008910 *
8911 * NOTE: Those stategies are not supported, so we will skip.
8912 */
8913 return (0);
8914 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008915 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008916 ns = XML_SCHEMAS_NO_NAMESPACE;
8917 else
8918 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008919
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008920 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008921 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008922 /*
8923 * There was a valid resource for the specified namespace already
8924 * defined, so skip.
8925 * TODO: This might be changed someday to allow import of
8926 * components from multiple documents for a single target namespace.
8927 */
8928 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008929 }
8930 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8931 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8932 else {
8933 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8934 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8935 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008936 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008937 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008938 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008939 * 2 Based on the location URI, identify an existing schema document,
8940 * either as a resource which is an XML document or a <schema> element
8941 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008942 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008943 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008944 * web which is or contains or references a <schema> element;
8945 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8946 *
8947 */
8948 if ((absolute == 0) && (node != NULL)) {
8949 xmlChar *base, *URI;
8950
8951 base = xmlNodeGetBase(node->doc, node);
8952 if (base == NULL) {
8953 URI = xmlBuildURI(location, node->doc->URL);
8954 } else {
8955 URI = xmlBuildURI(location, base);
8956 xmlFree(base);
8957 }
8958 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 xmlFree(URI);
8961 }
8962 }
8963 parserCtxt = xmlNewParserCtxt();
8964 if (parserCtxt == NULL) {
8965 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8966 "allocating a parser context", NULL);
8967 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008968 }
8969 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008970 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008971 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008972 xmlDictReference(parserCtxt->dict);
8973 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008974 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008975 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008976 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008977 * 2.1 The referent is (a fragment of) a resource which is an
8978 * XML document (see clause 1.1), which in turn corresponds to
8979 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008980 * set, which in turn corresponds to a valid schema.
8981 * TODO: What to do with the "fragment" stuff?
8982 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008983 * 2.2 The referent is a <schema> element information item in
8984 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008986 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008987 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008988 */
8989 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008990 xmlErrorPtr lerr;
8991 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008994 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008995 * If the doc is NULL and the parser error is an IO error we
8996 * will assume that the resource could not be located or accessed.
8997 *
8998 * TODO: Try to find specific error codes to react only on
8999 * localisation failures.
9000 *
9001 * TODO, FIXME: Check the spec: is a namespace added to the imported
9002 * namespaces, even if the schemaLocation did not provide
9003 * a resource? I guess so, since omitting the "schemaLocation"
9004 * attribute, imports a namespace as well.
9005 */
9006 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009007 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009008 xmlFreeParserCtxt(parserCtxt);
9009 return(0);
9010 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009011 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009012 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009013 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009014 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009015 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009016 xmlFreeParserCtxt(parserCtxt);
9017 return(XML_SCHEMAP_SRC_IMPORT_2_1);
9018 }
9019 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009020
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009021 root = xmlDocGetRootElement(*doc);
9022 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009023 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009024 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009025 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009026 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009027 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009028 xmlFreeDoc(*doc);
9029 *doc = NULL;
9030 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009031 }
9032
9033 xmlSchemaCleanupDoc(pctxt, root);
9034
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009035 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009036 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009037 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009038 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009039 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009040 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009041 xmlFreeDoc(*doc);
9042 *doc = NULL;
9043 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009044 }
9045 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009046 /*
9047 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009048 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009049 if (nsName == NULL) {
9050 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009051 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009052 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009053 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009054 "The XML schema to be imported is not expected "
9055 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009056 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009057 xmlFreeDoc(*doc);
9058 *doc = NULL;
9059 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9060 }
9061 } else {
9062 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009063 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009064 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009065 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009066 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009067 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009068 xmlFreeDoc(*doc);
9069 *doc = NULL;
9070 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9071 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009072 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009073 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009074 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009075 "The XML schema to be imported is expected to have a "
9076 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009077 "its target namespace of '%s'",
9078 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009079 xmlFreeDoc(*doc);
9080 *doc = NULL;
9081 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9082 }
9083 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009084 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009085 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009086 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9087 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009088 xmlFreeDoc(*doc);
9089 *doc = NULL;
9090 return (-1);
9091 }
9092 import->schemaLocation = location;
9093 import->doc = *doc;
9094 return (0);
9095}
William M. Brack2f2a6632004-08-20 23:09:47 +00009096
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009097static void
9098xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9099 xmlSchemaPtr schema,
9100 const xmlChar *targetNamespace,
9101 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009102{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009103 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009104 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009105
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009106 /*
9107 * Save and reset the context & schema.
9108 */
9109 oldURL = pctxt->URL;
9110 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009111 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009112 oldLocImps = pctxt->localImports;
9113 pctxt->localImports = NULL;
9114 oldNumLocImps = pctxt->nbLocalImports;
9115 pctxt->nbLocalImports = 0;
9116 oldSizeLocImps = pctxt->sizeLocalImports;
9117 pctxt->sizeLocalImports = 0;
9118 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009119 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009120 xmlSchemaClearSchemaDefaults(schema);
9121 oldTNS = schema->targetNamespace;
9122 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009123 if ((targetNamespace != NULL) &&
9124 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9125 /*
9126 * We are parsing the schema for schema!
9127 */
9128 pctxt->isS4S = 1;
9129 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009130 /*
9131 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009132 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009133 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9134 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9135 /*
9136 * Restore the context & schema.
9137 */
9138 schema->flags = oldFlags;
9139 schema->targetNamespace = oldTNS;
9140 if (pctxt->localImports != NULL)
9141 xmlFree((xmlChar *) pctxt->localImports);
9142 pctxt->localImports = oldLocImps;
9143 pctxt->nbLocalImports = oldNumLocImps;
9144 pctxt->sizeLocalImports = oldSizeLocImps;
9145 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009146 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009147}
9148
William M. Brack2f2a6632004-08-20 23:09:47 +00009149/**
9150 * xmlSchemaParseImport:
9151 * @ctxt: a schema validation context
9152 * @schema: the schema being built
9153 * @node: a subtree containing XML Schema informations
9154 *
9155 * parse a XML schema Import definition
9156 * *WARNING* this interface is highly subject to change
9157 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009158 * Returns 0 in case of success, a positive error code if
9159 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009160 */
9161static int
9162xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9163 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009164{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009165 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009166 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009167 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009168 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009169 xmlAttrPtr attr;
9170 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009171 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009172
9173 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9174 return (-1);
9175
9176 /*
9177 * Check for illegal attributes.
9178 */
9179 attr = node->properties;
9180 while (attr != NULL) {
9181 if (attr->ns == NULL) {
9182 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9183 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9184 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009185 xmlSchemaPIllegalAttrErr(ctxt,
9186 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9187 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009188 }
9189 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009190 xmlSchemaPIllegalAttrErr(ctxt,
9191 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9192 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009193 }
9194 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009195 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009196 /*
9197 * Extract and validate attributes.
9198 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009199 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9200 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009201 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009202 xmlSchemaPSimpleTypeErr(ctxt,
9203 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9204 NULL, node,
9205 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009206 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009207 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9208 }
9209
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009210 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9211 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009212 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009213 xmlSchemaPSimpleTypeErr(ctxt,
9214 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9215 NULL, node,
9216 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009217 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009218 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009219 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009220 /*
9221 * And now for the children...
9222 */
9223 child = node->children;
9224 if (IS_SCHEMA(child, "annotation")) {
9225 /*
9226 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009227 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009228 */
9229 child = child->next;
9230 }
9231 if (child != NULL) {
9232 xmlSchemaPContentErr(ctxt,
9233 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9234 NULL, NULL, node, child, NULL,
9235 "(annotation?)");
9236 }
9237 /*
9238 * Apply additional constraints.
9239 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009240 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009241 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009242 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9243 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009244 * targetNamespace [attribute].
9245 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009246 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009247 xmlSchemaPCustomErr(ctxt,
9248 XML_SCHEMAP_SRC_IMPORT_1_1,
9249 NULL, NULL, node,
9250 "The value of the attribute 'namespace' must not match "
9251 "the target namespace '%s' of the importing schema",
9252 schema->targetNamespace);
9253 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9254 }
9255 } else {
9256 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009257 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009258 * <schema> must have a targetNamespace [attribute].
9259 */
9260 if (schema->targetNamespace == NULL) {
9261 xmlSchemaPCustomErr(ctxt,
9262 XML_SCHEMAP_SRC_IMPORT_1_2,
9263 NULL, NULL, node,
9264 "The attribute 'namespace' must be existent if "
9265 "the importing schema has no target namespace",
9266 NULL);
9267 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9268 }
9269 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009270 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009271 * Add the namespace to the list of locally imported namespace.
9272 */
9273 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009274 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009275 sizeof(const xmlChar*));
9276 ctxt->sizeLocalImports = 10;
9277 ctxt->nbLocalImports = 0;
9278 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9279 ctxt->sizeLocalImports *= 2;
9280 ctxt->localImports = (const xmlChar **) xmlRealloc(
9281 (xmlChar **) ctxt->localImports,
9282 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9283 }
9284 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9285 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009286 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009287 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009288 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9289 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009290 schemaLocation, &doc, &targetNamespace, 0);
9291 if (ret != 0) {
9292 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009293 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009294 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009295 } else if (doc != NULL) {
9296 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9297 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009298 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009299
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009300 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009301}
9302
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009303/**
9304 * xmlSchemaParseInclude:
9305 * @ctxt: a schema validation context
9306 * @schema: the schema being built
9307 * @node: a subtree containing XML Schema informations
9308 *
9309 * parse a XML schema Include definition
9310 *
William M. Bracke7091952004-05-11 15:09:58 +00009311 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009312 * 1 in case of success.
9313 */
9314static int
9315xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9316 xmlNodePtr node)
9317{
9318 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009319 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009320 xmlDocPtr doc = NULL;
9321 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009322 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009323 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009324 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009325 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009326
9327
9328 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9329 return (-1);
9330
9331 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009332 * Check for illegal attributes.
9333 */
9334 attr = node->properties;
9335 while (attr != NULL) {
9336 if (attr->ns == NULL) {
9337 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9338 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009339 xmlSchemaPIllegalAttrErr(ctxt,
9340 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9341 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009342 }
9343 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009344 xmlSchemaPIllegalAttrErr(ctxt,
9345 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9346 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009347 }
9348 attr = attr->next;
9349 }
9350 /*
9351 * Extract and validate attributes.
9352 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009353 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009354 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009355 * Preliminary step, extract the URI-Reference for the include and
9356 * make an URI from the base.
9357 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009358 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9359 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009360 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009361 xmlChar *uri = NULL;
9362
9363 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9364 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009365 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009366 base = xmlNodeGetBase(node->doc, node);
9367 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009368 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009369 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009370 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009371 xmlFree(base);
9372 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009373 if (uri == NULL) {
9374 xmlSchemaPErr(ctxt,
9375 node,
9376 XML_SCHEMAP_INTERNAL,
9377 "Internal error: xmlSchemaParseInclude, "
9378 "could not build an URI from the schemaLocation.\n",
9379 NULL, NULL);
9380 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009381 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009382 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9383 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009384 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009385 xmlSchemaPMissingAttrErr(ctxt,
9386 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9387 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009388 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009389 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009390 /*
9391 * And now for the children...
9392 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009393 child = node->children;
9394 while (IS_SCHEMA(child, "annotation")) {
9395 /*
9396 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009397 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009398 */
9399 child = child->next;
9400 }
9401 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009402 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009403 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9404 NULL, NULL, node, child, NULL,
9405 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009406 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009407 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009408 * Report self-inclusion.
9409 */
9410 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9411 xmlSchemaPCustomErr(ctxt,
9412 XML_SCHEMAP_SRC_INCLUDE,
9413 NULL, NULL, node,
9414 "The schema document '%s' cannot include itself.",
9415 schemaLocation);
9416 return (XML_SCHEMAP_SRC_INCLUDE);
9417 }
9418 /*
9419 * Check if this one was already processed to avoid incorrect
9420 * duplicate component errors and infinite circular inclusion.
9421 */
9422 include = schema->includes;
9423 while (include != NULL) {
9424 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9425 targetNamespace = include->origTargetNamespace;
9426 if (targetNamespace == NULL) {
9427 /*
9428 * Chameleon include: skip only if it was build for
9429 * the targetNamespace of the including schema.
9430 */
9431 if (xmlStrEqual(schema->targetNamespace,
9432 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009433 goto check_targetNamespace;
9434 }
9435 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009436 goto check_targetNamespace;
9437 }
9438 }
9439 include = include->next;
9440 }
9441 /*
9442 * First step is to parse the input document into an DOM/Infoset
9443 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009444 */
9445 parserCtxt = xmlNewParserCtxt();
9446 if (parserCtxt == NULL) {
9447 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9448 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009449 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009450 }
9451
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009452 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9453 xmlDictFree(parserCtxt->dict);
9454 parserCtxt->dict = ctxt->dict;
9455 xmlDictReference(parserCtxt->dict);
9456 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009457
9458 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009459 NULL, SCHEMAS_PARSE_OPTIONS);
9460 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009461 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009462 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009463 * TODO: It is not an error for the ·actual value· of the
9464 * schemaLocation [attribute] to fail to resolve it all, in which
9465 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009466 * So do we need a warning report here?
9467 */
9468 xmlSchemaPCustomErr(ctxt,
9469 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009470 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009471 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009472 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009473 }
9474
9475 /*
9476 * Then extract the root of the schema
9477 */
9478 root = xmlDocGetRootElement(doc);
9479 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009480 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009481 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009482 NULL, NULL, node,
9483 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009484 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009485 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009486 }
9487
9488 /*
9489 * Remove all the blank text nodes
9490 */
9491 xmlSchemaCleanupDoc(ctxt, root);
9492
9493 /*
9494 * Check the schemas top level element
9495 */
9496 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009497 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009498 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009499 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009500 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009501 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009502 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009503 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009504
William M. Brack2f2a6632004-08-20 23:09:47 +00009505 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009506 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009507 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9508 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009509 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9510 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009511check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009512 if (targetNamespace != NULL) {
9513 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009514 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009515 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009516 NULL, NULL, node,
9517 "The target namespace of the included schema "
9518 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009519 "has no target namespace",
9520 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009521 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009522 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9523 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009524 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009525 NULL, NULL, node,
9526 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009527 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009528 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009529 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009530 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009531 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009532 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009533 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009534 } else
9535 wasConvertingNs = 1;
9536 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009537
9538 if (include != NULL)
9539 goto exit;
9540
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009541 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009542 * URGENT TODO: If the schema is a chameleon-include then copy the
9543 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009544 * of those components, do nothing otherwise.
9545 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009546 * for every destinct including targetNamespace; thus not performant at
9547 * the moment.
9548 * TODO: Check when the namespace in wildcards for chameleons needs
9549 * to be converted: before we built wildcard intersections or after.
9550 */
9551 /*
9552 * Register the include.
9553 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009554 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9555 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009556 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9557 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009558 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009559 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009560 include->next = schema->includes;
9561 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009562 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009563 * TODO: Use the resolved URI for the this location, since it might
9564 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009565 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009566 include->schemaLocation = schemaLocation;
9567 include->doc = doc;
9568 /*
9569 * In case of chameleons, the original target namespace will differ
9570 * from the resulting namespace.
9571 */
9572 include->origTargetNamespace = targetNamespace;
9573 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009574#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009575 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009576 xmlGenericError(xmlGenericErrorContext,
9577 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9578 " into TNS '%s'\n", schemaLocation,
9579 targetNamespace, schema->targetNamespace);
9580 else
9581 xmlGenericError(xmlGenericErrorContext,
9582 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9583 targetNamespace);
9584#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009585 /*
9586 * Compile the included schema.
9587 */
9588 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9589
9590exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009591 /*
9592 * Remove the converting flag.
9593 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009594 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009595 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009596 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009597 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009598
9599exit_invalid:
9600 if (doc != NULL) {
9601 if (include != NULL)
9602 include->doc = NULL;
9603 xmlFreeDoc(doc);
9604 }
9605 return (ctxt->err);
9606
9607exit_failure:
9608 if (doc != NULL) {
9609 if (include != NULL)
9610 include->doc = NULL;
9611 xmlFreeDoc(doc);
9612 }
9613 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009614}
9615
9616/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009617 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009618 * @ctxt: a schema validation context
9619 * @schema: the schema being built
9620 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009621 * @type: the "compositor" type
9622 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009623 *
9624 * parse a XML schema Sequence definition
9625 * *WARNING* this interface is highly subject to change
9626 *
William M. Bracke7091952004-05-11 15:09:58 +00009627 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009628 * 1 in case of success.
9629 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009630static xmlSchemaTreeItemPtr
9631xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9632 xmlNodePtr node, xmlSchemaTypeType type,
9633 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009634{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009635 xmlSchemaModelGroupPtr item;
9636 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009637 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009638 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009639 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009640 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009641
9642 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009643 return (NULL);
9644 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009645 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009646 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009647 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9648 if (item == NULL)
9649 return (NULL);
9650
9651 if (withParticle) {
9652 if (type == XML_SCHEMA_TYPE_ALL) {
9653 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009654 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009655 } else {
9656 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009657 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9658 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9659 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009660 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009661 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9662 /*
9663 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009664 */
9665 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9666 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009667 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009668 particle->children = (xmlSchemaTreeItemPtr) item;
9669 /*
9670 * Check for illegal attributes.
9671 */
9672 attr = node->properties;
9673 while (attr != NULL) {
9674 if (attr->ns == NULL) {
9675 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9676 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9677 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009678 xmlSchemaPIllegalAttrErr(ctxt,
9679 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9680 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009681 }
9682 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009683 xmlSchemaPIllegalAttrErr(ctxt,
9684 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9685 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009686 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009687 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009688 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009689 } else {
9690 /*
9691 * Check for illegal attributes.
9692 */
9693 attr = node->properties;
9694 while (attr != NULL) {
9695 if (attr->ns == NULL) {
9696 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009697 xmlSchemaPIllegalAttrErr(ctxt,
9698 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9699 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009700 }
9701 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009702 xmlSchemaPIllegalAttrErr(ctxt,
9703 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9704 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009705 }
9706 attr = attr->next;
9707 }
9708
William M. Brack2f2a6632004-08-20 23:09:47 +00009709 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009710
William M. Brack2f2a6632004-08-20 23:09:47 +00009711 /*
9712 * Extract and validate attributes.
9713 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009714 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009715 /*
9716 * And now for the children...
9717 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009718 child = node->children;
9719 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009720 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009721 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009722 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009723 oldcontainer = ctxt->container;
9724 ctxt->container = container;
9725 if (type == XML_SCHEMA_TYPE_ALL) {
9726 xmlSchemaParticlePtr part, last = NULL;
9727
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009728 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009729 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9730 schema, child, 0);
9731 if (part != NULL) {
9732 if (part->minOccurs > 1)
9733 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009734 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009735 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9736 if (part->maxOccurs > 1)
9737 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009738 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009739 "Invalid value for maxOccurs (must be 0 or 1)",
9740 NULL);
9741 if (last == NULL)
9742 item->children = (xmlSchemaTreeItemPtr) part;
9743 else
9744 last->next = (xmlSchemaTreeItemPtr) part;
9745 last = part;
9746 }
9747 child = child->next;
9748 }
9749 if (child != NULL) {
9750 xmlSchemaPContentErr(ctxt,
9751 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9752 NULL, NULL, node, child, NULL,
9753 "(annotation?, (annotation?, element*)");
9754 }
9755 } else {
9756 /* choice + sequence */
9757 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9758
9759 while ((IS_SCHEMA(child, "element")) ||
9760 (IS_SCHEMA(child, "group")) ||
9761 (IS_SCHEMA(child, "any")) ||
9762 (IS_SCHEMA(child, "choice")) ||
9763 (IS_SCHEMA(child, "sequence"))) {
9764
9765 if (IS_SCHEMA(child, "element")) {
9766 part = (xmlSchemaTreeItemPtr)
9767 xmlSchemaParseElement(ctxt, schema, child, 0);
9768 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009769 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009770 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9771 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009772 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009773 xmlSchemaParseAny(ctxt, schema, child);
9774 } else if (IS_SCHEMA(child, "choice")) {
9775 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9776 XML_SCHEMA_TYPE_CHOICE, 1);
9777 } else if (IS_SCHEMA(child, "sequence")) {
9778 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9779 XML_SCHEMA_TYPE_SEQUENCE, 1);
9780 }
9781 if (part != NULL) {
9782 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009783 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009784 else
9785 last->next = part;
9786 last = part;
9787 }
9788 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009789 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009790 if (child != NULL) {
9791 xmlSchemaPContentErr(ctxt,
9792 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9793 NULL, NULL, node, child, NULL,
9794 "(annotation?, (element | group | choice | sequence | any)*)");
9795 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009796 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009797 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009798 if (withParticle) {
9799 if ((min == 0) && (max == 0))
9800 return (NULL);
9801 else
9802 return ((xmlSchemaTreeItemPtr) particle);
9803 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009804 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009805}
9806
9807/**
9808 * xmlSchemaParseRestriction:
9809 * @ctxt: a schema validation context
9810 * @schema: the schema being built
9811 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009812 *
9813 * parse a XML schema Restriction definition
9814 * *WARNING* this interface is highly subject to change
9815 *
9816 * Returns the type definition or NULL in case of error
9817 */
9818static xmlSchemaTypePtr
9819xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009820 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009821{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009822 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009823 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009824 char buf[30];
9825 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009826 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009827
9828 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9829 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009830 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009831 type = ctxt->ctxtType;
9832 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009833
9834 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009835 * TODO: Is the container needed at all? the anonymous
9836 * items inside should generate unique names already.
9837 */
9838 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009839 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009840 /*
9841 * Check for illegal attributes.
9842 */
9843 attr = node->properties;
9844 while (attr != NULL) {
9845 if (attr->ns == NULL) {
9846 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9847 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009848 xmlSchemaPIllegalAttrErr(ctxt,
9849 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9850 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009851 }
9852 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009853 xmlSchemaPIllegalAttrErr(ctxt,
9854 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9855 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009856 }
9857 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009858 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009859 /*
9860 * Extract and validate attributes.
9861 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009862 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009863 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009864 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009865 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009866 /*
9867 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9868 * among its [children]), the simple type definition which is
9869 * the {content type} of the type definition ·resolved· to by
9870 * the ·actual value· of the base [attribute]"
9871 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009872 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009873 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009874 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009875 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009876 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009877 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009878 XML_SCHEMAP_S4S_ATTR_MISSING,
9879 type, node, "base", NULL);
9880 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009881 /*
9882 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009883 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009884 child = node->children;
9885 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009886 /*
9887 * Add the annotation to the simple type ancestor.
9888 */
9889 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9890 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009891 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009892 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009893 oldcontainer = ctxt->container;
9894 ctxt->container = container;
9895 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9896 /*
9897 * Corresponds to <simpleType><restriction><simpleType>.
9898 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009899 if (IS_SCHEMA(child, "simpleType")) {
9900 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009901 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009902 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009903 * Either the base [attribute] or the simpleType [child] of the
9904 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009905 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009906 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009907 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009908 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009909 "The attribute 'base' and the <simpleType> child are "
9910 "mutually exclusive", NULL);
9911 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009912 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009913 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009914 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009915 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009916 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009917 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009918 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9919 NULL, NULL, node, child,
9920 "Either the attribute 'base' or a <simpleType> child "
9921 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009922 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009923 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9924 /*
9925 * Corresponds to <complexType><complexContent><restriction>...
9926 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009927 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009928 * Model groups <all>, <choice> and <sequence>.
9929 */
9930 if (IS_SCHEMA(child, "all")) {
9931 type->subtypes = (xmlSchemaTypePtr)
9932 xmlSchemaParseModelGroup(ctxt, schema, child,
9933 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009934 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009935 } else if (IS_SCHEMA(child, "choice")) {
9936 type->subtypes = (xmlSchemaTypePtr)
9937 xmlSchemaParseModelGroup(ctxt,
9938 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9939 child = child->next;
9940 } else if (IS_SCHEMA(child, "sequence")) {
9941 type->subtypes = (xmlSchemaTypePtr)
9942 xmlSchemaParseModelGroup(ctxt, schema, child,
9943 XML_SCHEMA_TYPE_SEQUENCE, 1);
9944 child = child->next;
9945 /*
9946 * Model group reference <group>.
9947 */
9948 } else if (IS_SCHEMA(child, "group")) {
9949 type->subtypes = (xmlSchemaTypePtr)
9950 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9951 child = child->next;
9952 }
9953 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009954 /*
9955 * Corresponds to <complexType><simpleContent><restriction>...
9956 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009957 * "1.1 the simple type definition corresponding to the <simpleType>
9958 * among the [children] of <restriction> if there is one;"
9959 */
9960 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009961 /*
9962 * We will store the to-be-restricted simple type in
9963 * type->contentTypeDef *temporarily*.
9964 */
9965 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009966 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009967 if ( type->contentTypeDef == NULL)
9968 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009969 child = child->next;
9970 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009971 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009972
9973 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009974 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009975 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009976 /*
9977 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009978 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009979 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009980
Daniel Veillard01fa6152004-06-29 17:04:39 +00009981 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009982 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009983 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009984 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009985 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9986 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009987 * *Single Facet Value*
9988 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009989 while ((IS_SCHEMA(child, "minInclusive")) ||
9990 (IS_SCHEMA(child, "minExclusive")) ||
9991 (IS_SCHEMA(child, "maxInclusive")) ||
9992 (IS_SCHEMA(child, "maxExclusive")) ||
9993 (IS_SCHEMA(child, "totalDigits")) ||
9994 (IS_SCHEMA(child, "fractionDigits")) ||
9995 (IS_SCHEMA(child, "pattern")) ||
9996 (IS_SCHEMA(child, "enumeration")) ||
9997 (IS_SCHEMA(child, "whiteSpace")) ||
9998 (IS_SCHEMA(child, "length")) ||
9999 (IS_SCHEMA(child, "maxLength")) ||
10000 (IS_SCHEMA(child, "minLength"))) {
10001 facet = xmlSchemaParseFacet(ctxt, schema, child);
10002 if (facet != NULL) {
10003 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010004 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010005 else
10006 lastfacet->next = facet;
10007 lastfacet = facet;
10008 lastfacet->next = NULL;
10009 }
10010 child = child->next;
10011 }
10012 /*
10013 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010014 */
10015 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010016 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
10017
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010018 facet = type->facets;
10019 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010020 facetLink = (xmlSchemaFacetLinkPtr)
10021 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010022 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010023 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010024 xmlFree(facetLink);
10025 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010026 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010027 facetLink->facet = facet;
10028 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010029 if (lastFacetLink == NULL)
10030 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010031 else
10032 lastFacetLink->next = facetLink;
10033 lastFacetLink = facetLink;
10034 facet = facet->next;
10035 } while (facet != NULL);
10036 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010037 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010038 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
10039 /*
10040 * Attribute uses/declarations.
10041 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010042 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010043 /*
10044 * Attribute wildcard.
10045 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010046 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010047 type->attributeWildcard =
10048 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010049 child = child->next;
10050 }
10051 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010052 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010053 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10054 xmlSchemaPContentErr(ctxt,
10055 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010056 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010057 "annotation?, (group | all | choice | sequence)?, "
10058 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010059 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010060 xmlSchemaPContentErr(ctxt,
10061 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010062 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010063 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10064 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10065 "length | minLength | maxLength | enumeration | whiteSpace | "
10066 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10067 } else {
10068 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010069 xmlSchemaPContentErr(ctxt,
10070 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010071 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010072 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10073 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10074 "length | minLength | maxLength | enumeration | whiteSpace | "
10075 "pattern)*))");
10076 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010077 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010078 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010079 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010080}
10081
10082/**
10083 * xmlSchemaParseExtension:
10084 * @ctxt: a schema validation context
10085 * @schema: the schema being built
10086 * @node: a subtree containing XML Schema informations
10087 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010088 * Parses an <extension>, which is found inside a
10089 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010090 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010091 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010092 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010093 */
10094static xmlSchemaTypePtr
10095xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010096 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010097{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010098 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010099 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010100 char buf[30];
10101 const xmlChar *oldcontainer, *container;
10102 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010103
10104 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10105 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010106 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010107 type = ctxt->ctxtType;
10108 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010109
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010110 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10111 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10112 /*
10113 * Check for illegal attributes.
10114 */
10115 attr = node->properties;
10116 while (attr != NULL) {
10117 if (attr->ns == NULL) {
10118 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10119 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010120 xmlSchemaPIllegalAttrErr(ctxt,
10121 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10122 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010123 }
10124 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010125 xmlSchemaPIllegalAttrErr(ctxt,
10126 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10127 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010128 }
10129 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010130 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010131
10132 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010133
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010134 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010135 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010136 */
10137 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010138 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10139 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010140 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010141 XML_SCHEMAP_S4S_ATTR_MISSING,
10142 NULL, node, "base", NULL);
10143 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010144 /*
10145 * And now for the children...
10146 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010147 child = node->children;
10148 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010149 /*
10150 * Add the annotation to the type ancestor.
10151 */
10152 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10153 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010154 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010155 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010156 oldcontainer = ctxt->container;
10157 ctxt->container = container;
10158 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10159 /*
10160 * Corresponds to <complexType><complexContent><extension>... and:
10161 *
10162 * Model groups <all>, <choice>, <sequence> and <group>.
10163 */
10164 if (IS_SCHEMA(child, "all")) {
10165 type->subtypes = (xmlSchemaTypePtr)
10166 xmlSchemaParseModelGroup(ctxt, schema,
10167 child, XML_SCHEMA_TYPE_ALL, 1);
10168 child = child->next;
10169 } else if (IS_SCHEMA(child, "choice")) {
10170 type->subtypes = (xmlSchemaTypePtr)
10171 xmlSchemaParseModelGroup(ctxt, schema,
10172 child, XML_SCHEMA_TYPE_CHOICE, 1);
10173 child = child->next;
10174 } else if (IS_SCHEMA(child, "sequence")) {
10175 type->subtypes = (xmlSchemaTypePtr)
10176 xmlSchemaParseModelGroup(ctxt, schema,
10177 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10178 child = child->next;
10179 } else if (IS_SCHEMA(child, "group")) {
10180 type->subtypes = (xmlSchemaTypePtr)
10181 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10182 child = child->next;
10183 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010184 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010185 if (child != NULL) {
10186 /*
10187 * Attribute uses/declarations.
10188 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010189 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010190 /*
10191 * Attribute wildcard.
10192 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010193 if (IS_SCHEMA(child, "anyAttribute")) {
10194 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010195 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10196 child = child->next;
10197 }
10198 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010199 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010200 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10201 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010202 xmlSchemaPContentErr(ctxt,
10203 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010204 NULL, NULL, node, child, NULL,
10205 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010206 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010207 } else {
10208 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010209 xmlSchemaPContentErr(ctxt,
10210 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010211 NULL, NULL, node, child, NULL,
10212 "(annotation?, ((attribute | attributeGroup)*, "
10213 "anyAttribute?))");
10214 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010215 }
10216 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010217 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010218}
10219
10220/**
10221 * xmlSchemaParseSimpleContent:
10222 * @ctxt: a schema validation context
10223 * @schema: the schema being built
10224 * @node: a subtree containing XML Schema informations
10225 *
10226 * parse a XML schema SimpleContent definition
10227 * *WARNING* this interface is highly subject to change
10228 *
10229 * Returns the type definition or NULL in case of error
10230 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010231static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010232xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10233 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010234{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010235 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010236 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010237 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010238
10239 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010240 return (-1);
10241 /* Not a component, don't create it. */
10242 type = ctxt->ctxtType;
10243 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10244 /*
10245 * Check for illegal attributes.
10246 */
10247 attr = node->properties;
10248 while (attr != NULL) {
10249 if (attr->ns == NULL) {
10250 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010251 xmlSchemaPIllegalAttrErr(ctxt,
10252 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10253 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010254 }
10255 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010256 xmlSchemaPIllegalAttrErr(ctxt,
10257 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10258 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010259 }
10260 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010261 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010262
10263 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010264
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010265 /*
10266 * And now for the children...
10267 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010268 child = node->children;
10269 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010270 /*
10271 * Add the annotation to the complex type ancestor.
10272 */
10273 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10274 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010275 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010276 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010277 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010278 xmlSchemaParseRestriction(ctxt, schema, child,
10279 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010280 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010281 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010282 xmlSchemaParseExtension(ctxt, schema, child,
10283 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010284 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010285 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010286 if (child != NULL) {
10287 xmlSchemaPContentErr(ctxt,
10288 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010289 NULL, NULL, node, child, NULL,
10290 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010291 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010292 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010293}
10294
10295/**
10296 * xmlSchemaParseComplexContent:
10297 * @ctxt: a schema validation context
10298 * @schema: the schema being built
10299 * @node: a subtree containing XML Schema informations
10300 *
10301 * parse a XML schema ComplexContent definition
10302 * *WARNING* this interface is highly subject to change
10303 *
10304 * Returns the type definition or NULL in case of error
10305 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010306static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010307xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10308 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010309{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010310 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010311 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010312 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010313
10314 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010315 return (-1);
10316 /* Not a component, don't create it. */
10317 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010318 /*
10319 * Check for illegal attributes.
10320 */
10321 attr = node->properties;
10322 while (attr != NULL) {
10323 if (attr->ns == NULL) {
10324 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010325 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010326 {
10327 xmlSchemaPIllegalAttrErr(ctxt,
10328 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10329 NULL, NULL, attr);
10330 }
10331 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10332 xmlSchemaPIllegalAttrErr(ctxt,
10333 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10334 NULL, NULL, attr);
10335 }
10336 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010337 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010338
10339 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10340
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010341 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010342 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010343 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010344 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10345 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10346 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010347 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010348 child = node->children;
10349 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010350 /*
10351 * Add the annotation to the complex type ancestor.
10352 */
10353 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10354 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010355 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010356 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010357 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010358 xmlSchemaParseRestriction(ctxt, schema, child,
10359 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010360 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010361 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010362 xmlSchemaParseExtension(ctxt, schema, child,
10363 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010364 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010365 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010366 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010367 xmlSchemaPContentErr(ctxt,
10368 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10369 NULL, NULL, node, child,
10370 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010371 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010372 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010373}
10374
10375/**
10376 * xmlSchemaParseComplexType:
10377 * @ctxt: a schema validation context
10378 * @schema: the schema being built
10379 * @node: a subtree containing XML Schema informations
10380 *
10381 * parse a XML schema Complex Type definition
10382 * *WARNING* this interface is highly subject to change
10383 *
10384 * Returns the type definition or NULL in case of error
10385 */
10386static xmlSchemaTypePtr
10387xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010388 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010389{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010390 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010391 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010392 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010393 xmlAttrPtr attr;
10394 const xmlChar *attrValue;
10395 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010396 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010397 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010398
Daniel Veillard4255d502002-04-16 15:50:10 +000010399
10400 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10401 return (NULL);
10402
Daniel Veillard01fa6152004-06-29 17:04:39 +000010403 ctxtType = ctxt->ctxtType;
10404
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010405 if (topLevel) {
10406 attr = xmlSchemaGetPropNode(node, "name");
10407 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010408 xmlSchemaPMissingAttrErr(ctxt,
10409 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010410 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010411 } else if (xmlSchemaPValAttrNode(ctxt,
10412 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010413 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10414 return (NULL);
10415 }
10416 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010417
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010418 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010419 /*
10420 * Parse as local complex type definition.
10421 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010422 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010423 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10424 if (type == NULL)
10425 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010426 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010427 type->node = node;
10428 type->type = XML_SCHEMA_TYPE_COMPLEX;
10429 /*
10430 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010431 */
10432 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010433 /*
10434 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010435 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010436 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010437 if (type == NULL)
10438 return (NULL);
10439 type->node = node;
10440 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010441 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010442 }
10443 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010444 /*
10445 * Handle attributes.
10446 */
10447 attr = node->properties;
10448 while (attr != NULL) {
10449 if (attr->ns == NULL) {
10450 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10451 /*
10452 * Attribute "id".
10453 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010454 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10455 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010456 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10457 /*
10458 * Attribute "mixed".
10459 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010460 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010461 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010462 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10463 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010464 /*
10465 * Attributes of global complex type definitions.
10466 */
10467 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10468 /* Pass. */
10469 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10470 /*
10471 * Attribute "abstract".
10472 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010473 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10474 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010475 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10476 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10477 /*
10478 * Attribute "final".
10479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010480 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010481 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010482 if (xmlSchemaPValAttrBlockFinal(attrValue,
10483 &(type->flags),
10484 -1,
10485 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10486 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10487 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010488 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010489 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010490 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010491 type, (xmlNodePtr) attr, NULL,
10492 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010493 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010494 } else
10495 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010496 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10497 /*
10498 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010499 */
10500 attrValue = xmlSchemaGetNodeContent(ctxt,
10501 (xmlNodePtr) attr);
10502 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010503 -1,
10504 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010505 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010506 -1, -1, -1) != 0) {
10507 xmlSchemaPSimpleTypeErr(ctxt,
10508 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010509 type, (xmlNodePtr) attr, NULL,
10510 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010511 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010512 } else
10513 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010514 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010515 xmlSchemaPIllegalAttrErr(ctxt,
10516 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010517 &des, type, attr);
10518 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010519 } else {
10520 xmlSchemaPIllegalAttrErr(ctxt,
10521 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010522 &des, type, attr);
10523 }
10524 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010525 xmlSchemaPIllegalAttrErr(ctxt,
10526 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10527 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010528 }
10529 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010530 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010531 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010532 /*
10533 * Apply default "block" values.
10534 */
10535 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10536 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10537 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10538 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10539 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010540 if (! final) {
10541 /*
10542 * Apply default "block" values.
10543 */
10544 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10545 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10546 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10547 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10548 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010549 /*
10550 * And now for the children...
10551 */
10552 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010553 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010554 child = node->children;
10555 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010556 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10557 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010558 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010559 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010560 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010561 /*
10562 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010563 * Specifying mixed='true' when the <simpleContent>
10564 * alternative is chosen has no effect
10565 */
William M. Bracke7091952004-05-11 15:09:58 +000010566 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10567 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010568 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010569 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010570 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010571 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10572 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010573 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010574 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010575 /*
10576 * SPEC
10577 * "...the third alternative (neither <simpleContent> nor
10578 * <complexContent>) is chosen. This case is understood as shorthand
10579 * for complex content restricting the ·ur-type definition·, and the
10580 * details of the mappings should be modified as necessary.
10581 */
10582 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10583 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010584 /*
10585 * Parse model groups.
10586 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010587 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010588 type->subtypes = (xmlSchemaTypePtr)
10589 xmlSchemaParseModelGroup(ctxt, schema, child,
10590 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010591 child = child->next;
10592 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010593 type->subtypes = (xmlSchemaTypePtr)
10594 xmlSchemaParseModelGroup(ctxt, schema, child,
10595 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010596 child = child->next;
10597 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010598 type->subtypes = (xmlSchemaTypePtr)
10599 xmlSchemaParseModelGroup(ctxt, schema, child,
10600 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010601 child = child->next;
10602 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010603 type->subtypes = (xmlSchemaTypePtr)
10604 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010605 child = child->next;
10606 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010607 /*
10608 * Parse attribute decls/refs.
10609 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010610 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010611 /*
10612 * Parse attribute wildcard.
10613 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010614 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010615 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10616 child = child->next;
10617 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010618 }
10619 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010620 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010621 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010622 &des, type, node, child,
10623 NULL, "(annotation?, (simpleContent | complexContent | "
10624 "((group | all | choice | sequence)?, ((attribute | "
10625 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010626 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010627 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010628 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010629 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010630 return (type);
10631}
10632
Daniel Veillard4255d502002-04-16 15:50:10 +000010633/**
10634 * xmlSchemaParseSchema:
10635 * @ctxt: a schema validation context
10636 * @node: a subtree containing XML Schema informations
10637 *
10638 * parse a XML schema definition from a node set
10639 * *WARNING* this interface is highly subject to change
10640 *
10641 * Returns the internal XML Schema structure built from the resource or
10642 * NULL in case of error
10643 */
10644static xmlSchemaPtr
10645xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10646{
10647 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010648 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010649 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010650 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010651
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010652 /*
10653 * This one is called by xmlSchemaParse only and is used if
10654 * the schema to be parsed was specified via the API; i.e. not
10655 * automatically by the validated instance document.
10656 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010657 if ((ctxt == NULL) || (node == NULL))
10658 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010659 nberrors = ctxt->nberrors;
10660 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010661 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010662 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010663 xmlSchemaImportPtr import;
10664
Daniel Veillard4255d502002-04-16 15:50:10 +000010665 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010666 if (schema == NULL)
10667 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010668 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010669 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010670 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010671 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10672 /*
10673 * TODO: Should we proceed with an invalid target namespace?
10674 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010675 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010676 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10677 /*
10678 * We are parsing the schema for schema!
10679 */
10680 ctxt->isS4S = 1;
10681 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010682 } else {
10683 schema->targetNamespace = NULL;
10684 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010685 /*
10686 * Add the current ns name and location to the import table;
10687 * this is needed to have a consistent mechanism, regardless
10688 * if all schemata are constructed dynamically fired by the
10689 * instance or if the schema to be used was specified via
10690 * the API.
10691 */
10692 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10693 schema->targetNamespace);
10694 if (import == NULL) {
10695 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10696 NULL, NULL, (xmlNodePtr) ctxt->doc,
10697 "Internal error: xmlSchemaParseSchema, "
10698 "failed to add an import entry", NULL);
10699 xmlSchemaFree(schema);
10700 schema = NULL;
10701 return (NULL);
10702 }
10703 import->schemaLocation = ctxt->URL;
10704 /*
10705 * NOTE: We won't set the doc here, otherwise it will be freed
10706 * if the import struct is freed.
10707 * import->doc = ctxt->doc;
10708 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010709 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010710 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10711 } else {
10712 xmlDocPtr doc;
10713
10714 doc = node->doc;
10715
10716 if ((doc != NULL) && (doc->URL != NULL)) {
10717 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10718 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010719 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010720 } else {
10721 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10722 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010723 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010724 }
10725 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010726 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010727 if (ctxt->nberrors != 0) {
10728 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010729 xmlSchemaFree(schema);
10730 schema = NULL;
10731 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010732 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010733 if (schema != NULL)
10734 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010735 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010736#ifdef DEBUG
10737 if (schema == NULL)
10738 xmlGenericError(xmlGenericErrorContext,
10739 "xmlSchemaParse() failed\n");
10740#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010741 return (schema);
10742}
10743
10744/************************************************************************
10745 * *
10746 * Validating using Schemas *
10747 * *
10748 ************************************************************************/
10749
10750/************************************************************************
10751 * *
10752 * Reading/Writing Schemas *
10753 * *
10754 ************************************************************************/
10755
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010756#if 0 /* Will be enabled if it is clear what options are needed. */
10757/**
10758 * xmlSchemaParserCtxtSetOptions:
10759 * @ctxt: a schema parser context
10760 * @options: a combination of xmlSchemaParserOption
10761 *
10762 * Sets the options to be used during the parse.
10763 *
10764 * Returns 0 in case of success, -1 in case of an
10765 * API error.
10766 */
10767static int
10768xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10769 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010770
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010771{
10772 int i;
10773
10774 if (ctxt == NULL)
10775 return (-1);
10776 /*
10777 * WARNING: Change the start value if adding to the
10778 * xmlSchemaParseOption.
10779 */
10780 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10781 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010782 return (-1);
10783 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010784 }
10785 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010786 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010787}
10788
10789/**
10790 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010791 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010792 *
10793 * Returns the option combination of the parser context.
10794 */
10795static int
10796xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010797
10798{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010799 if (ctxt == NULL)
10800 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010801 else
10802 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010803}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010804#endif
10805
Daniel Veillard4255d502002-04-16 15:50:10 +000010806/**
10807 * xmlSchemaNewParserCtxt:
10808 * @URL: the location of the schema
10809 *
10810 * Create an XML Schemas parse context for that file/resource expected
10811 * to contain an XML Schemas file.
10812 *
10813 * Returns the parser context or NULL in case of error
10814 */
10815xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010816xmlSchemaNewParserCtxt(const char *URL)
10817{
Daniel Veillard4255d502002-04-16 15:50:10 +000010818 xmlSchemaParserCtxtPtr ret;
10819
10820 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010821 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010822
10823 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10824 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010825 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010826 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010827 return (NULL);
10828 }
10829 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010830 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010831 ret->dict = xmlDictCreate();
10832 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010833 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010834 return (ret);
10835}
10836
10837/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010838 * xmlSchemaNewMemParserCtxt:
10839 * @buffer: a pointer to a char array containing the schemas
10840 * @size: the size of the array
10841 *
10842 * Create an XML Schemas parse context for that memory buffer expected
10843 * to contain an XML Schemas file.
10844 *
10845 * Returns the parser context or NULL in case of error
10846 */
10847xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010848xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10849{
Daniel Veillard6045c902002-10-09 21:13:59 +000010850 xmlSchemaParserCtxtPtr ret;
10851
10852 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010853 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010854
10855 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10856 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010857 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010858 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010859 return (NULL);
10860 }
10861 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10862 ret->buffer = buffer;
10863 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010864 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010865 return (ret);
10866}
10867
10868/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010869 * xmlSchemaNewDocParserCtxt:
10870 * @doc: a preparsed document tree
10871 *
10872 * Create an XML Schemas parse context for that document.
10873 * NB. The document may be modified during the parsing process.
10874 *
10875 * Returns the parser context or NULL in case of error
10876 */
10877xmlSchemaParserCtxtPtr
10878xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10879{
10880 xmlSchemaParserCtxtPtr ret;
10881
10882 if (doc == NULL)
10883 return (NULL);
10884
10885 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10886 if (ret == NULL) {
10887 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10888 NULL);
10889 return (NULL);
10890 }
10891 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10892 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010893 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010894 /* The application has responsibility for the document */
10895 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010896
10897 return (ret);
10898}
10899
10900/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010901 * xmlSchemaFreeParserCtxt:
10902 * @ctxt: the schema parser context
10903 *
10904 * Free the resources associated to the schema parser context
10905 */
10906void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010907xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10908{
Daniel Veillard4255d502002-04-16 15:50:10 +000010909 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010910 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010911 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010912 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010913 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010914 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010915 xmlFree(ctxt->assemble);
10916 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010917 if (ctxt->vctxt != NULL) {
10918 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10919 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010920 if (ctxt->localImports != NULL)
10921 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010922 if (ctxt->substGroups != NULL)
10923 xmlHashFree(ctxt->substGroups,
10924 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010925 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010926 xmlFree(ctxt);
10927}
10928
10929/************************************************************************
10930 * *
10931 * Building the content models *
10932 * *
10933 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010934
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010935static void
10936xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000010937 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010938{
Daniel Veillarda980bef2005-07-18 21:34:03 +000010939 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010940 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010941 xmlSchemaSubstGroupPtr substGroup;
10942 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010943
10944 elemDecl = (xmlSchemaElementPtr) particle->children;
10945 /*
10946 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010947 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010948 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000010949 if (end == NULL)
10950 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010951 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10952 if (substGroup == NULL) {
10953 xmlSchemaPErr(pctxt, GET_NODE(particle),
10954 XML_SCHEMAP_INTERNAL,
10955 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10956 "declaration is marked having a subst. group but none "
10957 "available.\n", elemDecl->name, NULL);
10958 return;
10959 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000010960 if (counter >= 0) {
10961 /*
10962 * NOTE that we put the declaration in, even if it's abstract,
10963 */
10964 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
10965 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10966 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10967 /*
10968 * Add subst. group members.
10969 */
10970 for (i = 0; i < substGroup->members->nbItems; i++) {
10971 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10972 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10973 member->name, member->targetNamespace, member);
10974 }
10975 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010976 /*
10977 * NOTE that we put the declaration in, even if it's abstract,
10978 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010979 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010980 xmlAutomataNewTransition2(pctxt->am,
10981 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010982 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10983 /*
10984 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010985 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010986 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010987 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000010988 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
10989 member->name, member->targetNamespace,
10990 1, 1, member);
10991 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010992 }
10993 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010994 xmlAutomataStatePtr hop;
10995 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10996 UNBOUNDED : particle->maxOccurs - 1;
10997 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10998
10999 counter =
11000 xmlAutomataNewCounter(pctxt->am, minOccurs,
11001 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011002 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011003
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011004 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011005 xmlAutomataNewTransition2(pctxt->am,
11006 start, NULL,
11007 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011008 hop);
11009 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000011010 * Add subst. group members.
11011 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011012 for (i = 0; i < substGroup->members->nbItems; i++) {
11013 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11014 xmlAutomataNewEpsilon(pctxt->am,
11015 xmlAutomataNewTransition2(pctxt->am,
11016 start, NULL,
11017 member->name, member->targetNamespace, member),
11018 hop);
11019 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011020 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11021 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
11022 }
11023 if (particle->minOccurs == 0)
11024 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011025 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011026}
11027
11028static void
11029xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
11030 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011031{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011032 if (((xmlSchemaElementPtr) particle->children)->flags &
11033 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011034 /*
11035 * Substitution groups.
11036 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011037 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011038 } else {
11039 xmlSchemaElementPtr elemDecl;
11040 xmlAutomataStatePtr start;
11041
11042 elemDecl = (xmlSchemaElementPtr) particle->children;
11043
11044 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011045 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011046 if (particle->maxOccurs == 1) {
11047 start = ctxt->state;
11048 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011049 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11050 } else if ((particle->maxOccurs >= UNBOUNDED) &&
11051 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011052 /* Special case. */
11053 start = ctxt->state;
11054 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11055 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011056 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011057 } else {
11058 int counter;
11059 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11060 UNBOUNDED : particle->maxOccurs - 1;
11061 int minOccurs = particle->minOccurs < 1 ?
11062 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011063
11064 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011065 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11066 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11067 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11068 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11069 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11070 NULL, counter);
11071 }
11072 if (particle->minOccurs == 0)
11073 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11074 }
11075}
11076
Daniel Veillard4255d502002-04-16 15:50:10 +000011077/**
11078 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011079 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011080 * @particle: the particle component
11081 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011082 *
11083 * Generate the automata sequence needed for that type
11084 */
11085static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011086xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011087 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011088 const xmlChar * name)
11089{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011090 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011091 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011092 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011093 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011094 if (particle->children == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011095 PERROR_INT("xmlSchemaBuildAContentModel", "no term on particle");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011096 return;
11097 }
11098
11099 switch (particle->children->type) {
11100 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011101 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011102 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011103 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011104
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011105 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011106
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011107 start = pctxt->state;
11108 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011109
11110 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011111 if (wild->any == 1) {
11112 /*
11113 * We need to add both transitions:
11114 *
11115 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011116 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011117 pctxt->state =
11118 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011119 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011120 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011121 /*
11122 * 2. the {"*"} for elements in no namespace.
11123 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011124 pctxt->state =
11125 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011126 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011127 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011128
11129 } else if (wild->nsSet != NULL) {
11130 ns = wild->nsSet;
11131 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011132 pctxt->state = start;
11133 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
11134 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
11135 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011136 ns = ns->next;
11137 } while (ns != NULL);
11138
11139 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000011140 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
11141 start, end, BAD_CAST "*", wild->negNsSet->value,
11142 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011143 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011144 } else {
11145 int counter;
11146 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011147 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011148 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011149 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011150 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011151
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011152 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11153 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011154 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011155 pctxt->state =
11156 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011157 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011158 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
11159 pctxt->state =
11160 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011161 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011162 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011163 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011164 ns = wild->nsSet;
11165 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011166 pctxt->state =
11167 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011168 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011169 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011170 ns = ns->next;
11171 } while (ns != NULL);
11172
11173 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011174 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000011175 start, hop, BAD_CAST "*", wild->negNsSet->value,
11176 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011177 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011178 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11179 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011180 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011181 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011182 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011183 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011184 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011185 break;
11186 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011187 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011188 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011189 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011190 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011191 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011192
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011193 /*
11194 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011195 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011196 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011197 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11198 sub = particle->children->children;
11199 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011200 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011201 (xmlSchemaParticlePtr) sub, name);
11202 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011203 }
11204 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011205 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011206
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011207 if (particle->maxOccurs >= UNBOUNDED) {
11208 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011209 xmlAutomataStatePtr tmp;
11210 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011211
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011212 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011213 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011214 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011215
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011216 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011217 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011218
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011219 sub = particle->children->children;
11220 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011221 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011222 (xmlSchemaParticlePtr) sub, name);
11223 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011224 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011225 tmp = pctxt->state;
11226 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011227 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011228 pctxt->state =
11229 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011230 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011231
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011232 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011233 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000011234 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011235 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011236
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011237 sub = particle->children->children;
11238 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011239 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011240 (xmlSchemaParticlePtr) sub, name);
11241 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011242 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011243 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011244 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011245 /*
11246 * epsilon needed to block previous trans from
11247 * being allowed to enter back from another
11248 * construct
11249 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011250 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
11251 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011252 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011253 xmlAutomataNewEpsilon(pctxt->am,
11254 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011255 }
11256 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011257 } else if ((particle->maxOccurs > 1)
11258 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011259 xmlAutomataStatePtr tmp;
11260 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011261
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011262 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011263 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011264 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011265
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011266 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011267 particle->minOccurs - 1,
11268 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011269
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011270 sub = particle->children->children;
11271 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011272 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011273 (xmlSchemaParticlePtr) sub, name);
11274 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011275 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011276 tmp = pctxt->state;
11277 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011278 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011279 pctxt->state =
11280 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011281 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011282 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011283 xmlAutomataNewEpsilon(pctxt->am,
11284 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011285 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011286 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011287 sub = particle->children->children;
11288 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011289 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011290 (xmlSchemaParticlePtr) sub, name);
11291 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011292 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011293 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011294 xmlAutomataNewEpsilon(pctxt->am, oldstate,
11295 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011296 }
11297 }
11298 }
11299 break;
11300 }
11301 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011302 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011303 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011304
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011305 start = pctxt->state;
11306 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011307
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011308 /*
11309 * iterate over the subtypes and remerge the end with an
11310 * epsilon transition
11311 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011312 if (particle->maxOccurs == 1) {
11313 sub = particle->children->children;
11314 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011315 pctxt->state = start;
11316 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011317 (xmlSchemaParticlePtr) sub, name);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011318 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011319 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011320 }
11321 } else {
11322 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011323 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011324 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11325 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011326 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011327 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011328
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011329 /*
11330 * use a counter to keep track of the number of transtions
11331 * which went through the choice.
11332 */
11333 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011334 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11335 hop = xmlAutomataNewState(pctxt->am);
11336 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011337
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011338 sub = particle->children->children;
11339 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011340 pctxt->state = base;
11341 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011342 (xmlSchemaParticlePtr) sub, name);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011343 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011344 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011345 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011346 xmlAutomataNewEpsilon(pctxt->am, start, base);
11347 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
11348 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011349 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011350 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011351 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011352 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011353 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011354 break;
11355 }
11356 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000011357 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011358 xmlSchemaParticlePtr sub;
11359 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011360 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011361
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011362 sub = (xmlSchemaParticlePtr) particle->children->children;
11363 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011364 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011365 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011366 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011367 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011368
11369 elemDecl = (xmlSchemaElementPtr) sub->children;
11370 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011371 PERROR_INT("xmlSchemaBuildAContentModel",
11372 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011373 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011374 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011375 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011376 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011377 * {particles} of the group must be 0 or 1; this is
11378 * already ensured during the parse of the content of
11379 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011380 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011381 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11382 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011383
Daniel Veillarda980bef2005-07-18 21:34:03 +000011384 /*
11385 * This is an abstract group, we need to share
11386 * the same counter for all the element transitions
11387 * derived from the group
11388 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011389 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011390 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011391 xmlSchemaBuildContentModelForSubstGroup(pctxt,
11392 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000011393 } else {
11394 if ((sub->minOccurs == 1) &&
11395 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011396 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
11397 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011398 elemDecl->name,
11399 elemDecl->targetNamespace,
11400 1, 1, elemDecl);
11401 } else if ((sub->minOccurs == 0) &&
11402 (sub->maxOccurs == 1)) {
11403
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011404 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
11405 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011406 elemDecl->name,
11407 elemDecl->targetNamespace,
11408 0,
11409 1,
11410 elemDecl);
11411 }
11412 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011413 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011414 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011415 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011416 pctxt->state =
11417 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011418 break;
11419 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011420 case XML_SCHEMA_TYPE_GROUP:
11421 /*
11422 * If we hit a model group definition, then this means that
11423 * it was empty, thus was not substituted for the containing
11424 * model group. Just do nothing in this case.
11425 */
11426 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011427 default:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011428 xmlSchemaPInternalErr(pctxt, "xmlSchemaBuildAContentModel",
11429 "found unexpected term of type '%s' in content model of complex "
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000011430 "type '%s'",
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011431 xmlSchemaCompTypeToString(particle->children->type), name);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000011432 xmlGenericError(xmlGenericErrorContext,
11433 "Unexpected type: %d\n", particle->children->type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011434 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011435 }
11436}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011437
Daniel Veillard4255d502002-04-16 15:50:10 +000011438/**
11439 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011440 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011441 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011442 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011443 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011444 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011445 */
11446static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011447xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011448 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011449 const xmlChar * name)
11450{
Daniel Veillard4255d502002-04-16 15:50:10 +000011451 xmlAutomataStatePtr start;
11452
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011453 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11454 (type->contModel != NULL) ||
11455 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11456 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011457 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011458
11459#ifdef DEBUG_CONTENT
11460 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011461 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011462#endif
11463
Daniel Veillard4255d502002-04-16 15:50:10 +000011464 ctxt->am = xmlNewAutomata();
11465 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011466 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011467 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011468 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011469 }
11470 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011471 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011472 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011473 type->contModel = xmlAutomataCompile(ctxt->am);
11474 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011475 xmlSchemaPCustomErr(ctxt,
11476 XML_SCHEMAP_INTERNAL,
11477 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011478 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011479 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011480 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011481 XML_SCHEMAP_NOT_DETERMINISTIC,
11482 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011483 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011484 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011485 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011486#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011487 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011488 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011489 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011490#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011491 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011492 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011493 xmlFreeAutomata(ctxt->am);
11494 ctxt->am = NULL;
11495}
11496
11497/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011498 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011499 * @elem: the schema element context
11500 * @ctxt: the schema parser context
11501 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011502 * Resolves the references of an element declaration
11503 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011504 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011505 */
11506static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011507xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011508 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011509 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011510 const xmlChar * context ATTRIBUTE_UNUSED,
11511 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011512{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011513 if ((ctxt == NULL) || (elemDecl == NULL) ||
11514 ((elemDecl != NULL) &&
11515 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011516 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011517 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011518
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011519 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011520 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011521
11522 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011523 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011524 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011525 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011526 elemDecl->namedTypeNs);
11527 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011528 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011529 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011530 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011531 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011532 XML_SCHEMA_TYPE_BASIC, "type definition");
11533 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011534 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011535 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011536 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011537 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011538
Daniel Veillardc0826a72004-08-10 14:17:33 +000011539 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011540 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011541 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011542 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011543 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11544 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011545 if (substHead == NULL) {
11546 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011547 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011548 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011549 "substitutionGroup", elemDecl->substGroup,
11550 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011551 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011552 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011553 /*
11554 * Set the "substitution group affiliation".
11555 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011556 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011557 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011558 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011559 * (type definition)...otherwise the {type definition} of the
11560 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011561 * the substitutionGroup [attribute], if present
11562 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011563 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011564 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011565 }
11566 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011567 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11568 (elemDecl->substGroup == NULL))
11569 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011570}
11571
11572/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011573 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011574 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011575 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011576 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011577 * Checks and builds the "member type definitions" property of the union
11578 * simple type. This handles part (1), part (2) is done in
11579 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11580 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011581 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011582 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011583static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011584xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11585 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011586{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011587
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011588 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011589 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011590
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011591 /*
11592 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11593 * define the explicit members as the type definitions ·resolved·
11594 * to by the items in the ·actual value· of the memberTypes [attribute],
11595 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011596 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011597 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011598 /*
11599 * Resolve references.
11600 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011601 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011602 lastLink = NULL;
11603 while (link != NULL) {
11604 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011605
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011606 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11607 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11608
11609 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11610 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11611 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011612 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011613 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11614 /*
11615 * Remove the member type link.
11616 */
11617 if (lastLink == NULL)
11618 type->memberTypes = link->next;
11619 else
11620 lastLink->next = link->next;
11621 newLink = link;
11622 link = link->next;
11623 xmlFree(newLink);
11624 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011625 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011626 lastLink = link;
11627 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011628 }
11629 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011630 /*
11631 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011632 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011633 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011634 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011635 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11636 if (link == NULL) {
11637 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11638 return (-1);
11639 }
11640 link->type = memberType;
11641 link->next = NULL;
11642 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011643 type->memberTypes = link;
11644 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011645 lastLink->next = link;
11646 lastLink = link;
11647 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011648 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011649 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011650}
11651
Daniel Veillard4255d502002-04-16 15:50:10 +000011652/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011653 * xmlSchemaIsDerivedFromBuiltInType:
11654 * @ctxt: the schema parser context
11655 * @type: the type definition
11656 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011657 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011658 *
11659 * Returns 1 if the type has the given value type, or
11660 * is derived from such a type.
11661 */
William M. Brack803812b2004-06-03 02:11:24 +000011662static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011663xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011664{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011665 if (type == NULL)
11666 return (0);
11667 if (IS_COMPLEX_TYPE(type))
11668 return (0);
11669 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11670 if (type->builtInType == valType)
11671 return(1);
11672 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11673 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11674 return (0);
11675 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11676 } else
11677 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011678
11679 return (0);
11680}
11681
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011682#if 0
11683/**
11684 * xmlSchemaIsDerivedFromBuiltInType:
11685 * @ctxt: the schema parser context
11686 * @type: the type definition
11687 * @valType: the value type
11688 *
11689 *
11690 * Returns 1 if the type has the given value type, or
11691 * is derived from such a type.
11692 */
11693static int
11694xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11695{
11696 if (type == NULL)
11697 return (0);
11698 if (IS_COMPLEX_TYPE(type))
11699 return (0);
11700 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11701 if (type->builtInType == valType)
11702 return(1);
11703 return (0);
11704 } else
11705 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11706
11707 return (0);
11708}
11709#endif
11710
11711static xmlSchemaTypePtr
11712xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11713{
11714 if (type == NULL)
11715 return (NULL);
11716 if (IS_COMPLEX_TYPE(type))
11717 return (NULL);
11718 if (type->type == XML_SCHEMA_TYPE_BASIC)
11719 return(type);
11720 else
11721 return(xmlSchemaQueryBuiltInType(type->subtypes));
11722
11723 return (NULL);
11724}
11725
Daniel Veillard3646d642004-06-02 19:19:14 +000011726/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011727 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011728 * @type: the simpleType definition
11729 *
11730 * Returns the primitive type of the given type or
11731 * NULL in case of error.
11732 */
11733static xmlSchemaTypePtr
11734xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11735{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011736
Daniel Veillard01fa6152004-06-29 17:04:39 +000011737 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011738 /*
11739 * Note that anySimpleType is actually not a primitive type
11740 * but we need that here.
11741 */
11742 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11743 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011744 return (type);
11745 type = type->baseType;
11746 }
11747
11748 return (NULL);
11749}
11750
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011751#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011752/**
11753 * xmlSchemaGetBuiltInTypeAncestor:
11754 * @type: the simpleType definition
11755 *
11756 * Returns the primitive type of the given type or
11757 * NULL in case of error.
11758 */
11759static xmlSchemaTypePtr
11760xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11761{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011762 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011763 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011764 while (type != NULL) {
11765 if (type->type == XML_SCHEMA_TYPE_BASIC)
11766 return (type);
11767 type = type->baseType;
11768 }
11769
11770 return (NULL);
11771}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011772#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011773
Daniel Veillard01fa6152004-06-29 17:04:39 +000011774/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011775 * xmlSchemaBuildAttributeUsesOwned:
11776 * @ctxt: the schema parser context
11777 * @type: the complex type definition
11778 * @cur: the attribute declaration list
11779 * @lastUse: the top of the attribute use list
11780 *
11781 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011782 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011783 * xmlSchemaBuildAttributeValidation only.
11784 */
11785static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011786xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011787 xmlSchemaAttributePtr cur,
11788 xmlSchemaAttributeLinkPtr *uses,
11789 xmlSchemaAttributeLinkPtr *lastUse)
11790{
11791 xmlSchemaAttributeLinkPtr tmp;
11792 while (cur != NULL) {
11793 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011794 /*
11795 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11796 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011797 * <attributeGroup> [children], if any."
11798 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011799 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11800 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011801 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011802 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011803 }
11804 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011805 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011806 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011807 */
11808 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011809 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11810 if (tmp == NULL) {
11811 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11812 return (-1);
11813 }
11814 tmp->attr = cur;
11815 tmp->next = NULL;
11816 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011817 *uses = tmp;
11818 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011819 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011820 *lastUse = tmp;
11821 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011822 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011823 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011824 return (0);
11825}
11826
Daniel Veillard50355f02004-06-08 17:52:16 +000011827/**
11828 * xmlSchemaCloneWildcardNsConstraints:
11829 * @ctxt: the schema parser context
11830 * @dest: the destination wildcard
11831 * @source: the source wildcard
11832 *
11833 * Clones the namespace constraints of source
11834 * and assignes them to dest.
11835 * Returns -1 on internal error, 0 otherwise.
11836 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011837static int
11838xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11839 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011840 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011841{
11842 xmlSchemaWildcardNsPtr cur, tmp, last;
11843
11844 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011845 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011846 (*dest)->any = source->any;
11847 cur = source->nsSet;
11848 last = NULL;
11849 while (cur != NULL) {
11850 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11851 if (tmp == NULL)
11852 return(-1);
11853 tmp->value = cur->value;
11854 if (last == NULL)
11855 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011856 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011857 last->next = tmp;
11858 last = tmp;
11859 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011860 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011861 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011862 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011863 if (source->negNsSet != NULL) {
11864 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11865 if ((*dest)->negNsSet == NULL)
11866 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011867 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011868 } else
11869 (*dest)->negNsSet = NULL;
11870 return(0);
11871}
11872
Daniel Veillard50355f02004-06-08 17:52:16 +000011873/**
11874 * xmlSchemaUnionWildcards:
11875 * @ctxt: the schema parser context
11876 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011877 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011878 *
11879 * Unions the namespace constraints of the given wildcards.
11880 * @completeWild will hold the resulting union.
11881 * Returns a positive error code on failure, -1 in case of an
11882 * internal error, 0 otherwise.
11883 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011884static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011885xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011886 xmlSchemaWildcardPtr completeWild,
11887 xmlSchemaWildcardPtr curWild)
11888{
11889 xmlSchemaWildcardNsPtr cur, curB, tmp;
11890
11891 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011892 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011893 * value.
11894 */
11895 if ((completeWild->any == curWild->any) &&
11896 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11897 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011898
Daniel Veillard3646d642004-06-02 19:19:14 +000011899 if ((completeWild->negNsSet == NULL) ||
11900 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011901
Daniel Veillard3646d642004-06-02 19:19:14 +000011902 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011903 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011904
11905 /*
11906 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011907 */
11908 cur = completeWild->nsSet;
11909 while (cur != NULL) {
11910 found = 0;
11911 curB = curWild->nsSet;
11912 while (curB != NULL) {
11913 if (cur->value == curB->value) {
11914 found = 1;
11915 break;
11916 }
11917 curB = curB->next;
11918 }
11919 if (!found)
11920 break;
11921 cur = cur->next;
11922 }
11923 if (found)
11924 return(0);
11925 } else
11926 return(0);
11927 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011928 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011929 /*
11930 * 2 If either O1 or O2 is any, then any must be the value
11931 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011932 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011933 if (completeWild->any == 0) {
11934 completeWild->any = 1;
11935 if (completeWild->nsSet != NULL) {
11936 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11937 completeWild->nsSet = NULL;
11938 }
11939 if (completeWild->negNsSet != NULL) {
11940 xmlFree(completeWild->negNsSet);
11941 completeWild->negNsSet = NULL;
11942 }
11943 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011944 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011945 }
11946 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011947 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011948 * then the union of those sets must be the value.
11949 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011950 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011951 int found;
11952 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011953
Daniel Veillard3646d642004-06-02 19:19:14 +000011954 cur = curWild->nsSet;
11955 start = completeWild->nsSet;
11956 while (cur != NULL) {
11957 found = 0;
11958 curB = start;
11959 while (curB != NULL) {
11960 if (cur->value == curB->value) {
11961 found = 1;
11962 break;
11963 }
11964 curB = curB->next;
11965 }
11966 if (!found) {
11967 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011968 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011969 return (-1);
11970 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011971 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011972 completeWild->nsSet = tmp;
11973 }
11974 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011975 }
11976
Daniel Veillard3646d642004-06-02 19:19:14 +000011977 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011978 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011979 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011980 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011981 * or ·absent·), then a pair of not and ·absent· must be the value.
11982 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011983 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011984 (curWild->negNsSet != NULL) &&
11985 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11986 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011987
11988 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011989 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011990 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011991 * 5.
11992 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011993 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011994 (completeWild->negNsSet->value != NULL) &&
11995 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011996 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011997 (curWild->negNsSet->value != NULL) &&
11998 (completeWild->nsSet != NULL))) {
11999
12000 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012001
Daniel Veillard3646d642004-06-02 19:19:14 +000012002 if (completeWild->nsSet != NULL) {
12003 cur = completeWild->nsSet;
12004 curB = curWild->negNsSet;
12005 } else {
12006 cur = curWild->nsSet;
12007 curB = completeWild->negNsSet;
12008 }
12009 nsFound = 0;
12010 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012011 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012012 absentFound = 1;
12013 else if (cur->value == curB->value)
12014 nsFound = 1;
12015 if (nsFound && absentFound)
12016 break;
12017 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012018 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012019
12020 if (nsFound && absentFound) {
12021 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012022 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000012023 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012024 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012025 completeWild->any = 1;
12026 if (completeWild->nsSet != NULL) {
12027 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12028 completeWild->nsSet = NULL;
12029 }
12030 if (completeWild->negNsSet != NULL) {
12031 xmlFree(completeWild->negNsSet);
12032 completeWild->negNsSet = NULL;
12033 }
12034 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012035 /*
12036 * 5.2 If the set S includes the negated namespace name
12037 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000012038 * be the value.
12039 */
12040 if (completeWild->nsSet != NULL) {
12041 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12042 completeWild->nsSet = NULL;
12043 }
12044 if (completeWild->negNsSet == NULL) {
12045 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12046 if (completeWild->negNsSet == NULL)
12047 return (-1);
12048 }
12049 completeWild->negNsSet->value = NULL;
12050 } else if ((!nsFound) && absentFound) {
12051 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012052 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012053 * namespace name, then the union is not expressible.
12054 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012055 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012056 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012057 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012058 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012059 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012060 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012061 /*
12062 * 5.4 If the set S does not include either the negated namespace
12063 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012064 * and a namespace name must be the value.
12065 */
12066 if (completeWild->negNsSet == NULL) {
12067 if (completeWild->nsSet != NULL) {
12068 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12069 completeWild->nsSet = NULL;
12070 }
12071 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12072 if (completeWild->negNsSet == NULL)
12073 return (-1);
12074 completeWild->negNsSet->value = curWild->negNsSet->value;
12075 }
12076 }
12077 return (0);
12078 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012079 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012080 * 6.
12081 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012082 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012083 (completeWild->negNsSet->value == NULL) &&
12084 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012085 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012086 (curWild->negNsSet->value == NULL) &&
12087 (completeWild->nsSet != NULL))) {
12088
12089 if (completeWild->nsSet != NULL) {
12090 cur = completeWild->nsSet;
12091 } else {
12092 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012093 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012094 while (cur != NULL) {
12095 if (cur->value == NULL) {
12096 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012097 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012098 * value.
12099 */
12100 completeWild->any = 1;
12101 if (completeWild->nsSet != NULL) {
12102 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12103 completeWild->nsSet = NULL;
12104 }
12105 if (completeWild->negNsSet != NULL) {
12106 xmlFree(completeWild->negNsSet);
12107 completeWild->negNsSet = NULL;
12108 }
12109 return (0);
12110 }
12111 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012112 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012113 if (completeWild->negNsSet == NULL) {
12114 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012115 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012116 * and ·absent· must be the value.
12117 */
12118 if (completeWild->nsSet != NULL) {
12119 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12120 completeWild->nsSet = NULL;
12121 }
12122 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12123 if (completeWild->negNsSet == NULL)
12124 return (-1);
12125 completeWild->negNsSet->value = NULL;
12126 }
12127 return (0);
12128 }
12129 return (0);
12130
12131}
12132
Daniel Veillard50355f02004-06-08 17:52:16 +000012133/**
12134 * xmlSchemaIntersectWildcards:
12135 * @ctxt: the schema parser context
12136 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012137 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012138 *
12139 * Intersects the namespace constraints of the given wildcards.
12140 * @completeWild will hold the resulting intersection.
12141 * Returns a positive error code on failure, -1 in case of an
12142 * internal error, 0 otherwise.
12143 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012144static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012145xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012146 xmlSchemaWildcardPtr completeWild,
12147 xmlSchemaWildcardPtr curWild)
12148{
William M. Brack803812b2004-06-03 02:11:24 +000012149 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012150
12151 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012152 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012153 * value.
12154 */
12155 if ((completeWild->any == curWild->any) &&
12156 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12157 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012158
Daniel Veillard3646d642004-06-02 19:19:14 +000012159 if ((completeWild->negNsSet == NULL) ||
12160 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012161
Daniel Veillard3646d642004-06-02 19:19:14 +000012162 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012163 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012164
12165 /*
12166 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012167 */
12168 cur = completeWild->nsSet;
12169 while (cur != NULL) {
12170 found = 0;
12171 curB = curWild->nsSet;
12172 while (curB != NULL) {
12173 if (cur->value == curB->value) {
12174 found = 1;
12175 break;
12176 }
12177 curB = curB->next;
12178 }
12179 if (!found)
12180 break;
12181 cur = cur->next;
12182 }
12183 if (found)
12184 return(0);
12185 } else
12186 return(0);
12187 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012188 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012189 /*
12190 * 2 If either O1 or O2 is any, then the other must be the value.
12191 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012192 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012193 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012194 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012195 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012196 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012197 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012198 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12199 * name or ·absent·) and the other is a set of (namespace names or
12200 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012201 * the set, minus ·absent· if it was in the set, must be the value.
12202 */
12203 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12204 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12205 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012206
Daniel Veillard3646d642004-06-02 19:19:14 +000012207 if (completeWild->nsSet == NULL) {
12208 neg = completeWild->negNsSet->value;
12209 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12210 return(-1);
12211 } else
12212 neg = curWild->negNsSet->value;
12213 /*
12214 * Remove absent and negated.
12215 */
12216 prev = NULL;
12217 cur = completeWild->nsSet;
12218 while (cur != NULL) {
12219 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012220 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012221 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012222 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012223 prev->next = cur->next;
12224 xmlFree(cur);
12225 break;
12226 }
12227 prev = cur;
12228 cur = cur->next;
12229 }
12230 if (neg != NULL) {
12231 prev = NULL;
12232 cur = completeWild->nsSet;
12233 while (cur != NULL) {
12234 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012235 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012236 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012237 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012238 prev->next = cur->next;
12239 xmlFree(cur);
12240 break;
12241 }
12242 prev = cur;
12243 cur = cur->next;
12244 }
12245 }
12246
12247 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012248 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012249 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012250 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012251 * then the intersection of those sets must be the value.
12252 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012253 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012254 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012255
Daniel Veillard3646d642004-06-02 19:19:14 +000012256 cur = completeWild->nsSet;
12257 prev = NULL;
12258 while (cur != NULL) {
12259 found = 0;
12260 curB = curWild->nsSet;
12261 while (curB != NULL) {
12262 if (cur->value == curB->value) {
12263 found = 1;
12264 break;
12265 }
12266 curB = curB->next;
12267 }
12268 if (!found) {
12269 if (prev == NULL)
12270 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012271 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012272 prev->next = cur->next;
12273 tmp = cur->next;
12274 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012275 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012276 continue;
12277 }
12278 prev = cur;
12279 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012280 }
12281
Daniel Veillard3646d642004-06-02 19:19:14 +000012282 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012283 }
12284 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012285 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012286 */
12287 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012288 (curWild->negNsSet != NULL) &&
12289 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012290 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012291 (curWild->negNsSet->value != NULL)) {
12292
12293 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012294 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012295 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012296 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012297 }
12298 /*
12299 * 6 If the one is a negation of a namespace name and the other
12300 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012301 * of a namespace name must be the value.
12302 */
12303 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12304 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012305 (completeWild->negNsSet->value == NULL)) {
12306 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012307 }
12308 return(0);
12309}
12310
Daniel Veillard50355f02004-06-08 17:52:16 +000012311/**
12312 * xmlSchemaIsWildcardNsConstraintSubset:
12313 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012314 * @sub: the first wildcard
12315 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012316 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012317 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12318 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012319 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012320 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012321 */
12322static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012323xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12324 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012325{
Daniel Veillard50355f02004-06-08 17:52:16 +000012326 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012327 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012328 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012329 if (super->any)
12330 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012331 /*
12332 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12333 * 2.2 super must be a pair of not and the same value.
12334 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012335 if ((sub->negNsSet != NULL) &&
12336 (super->negNsSet != NULL) &&
12337 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012338 return (0);
12339 /*
12340 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012341 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012342 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012343 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012344 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012345 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012346 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012347 xmlSchemaWildcardNsPtr cur, curB;
12348 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012349
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012350 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012351 while (cur != NULL) {
12352 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012353 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012354 while (curB != NULL) {
12355 if (cur->value == curB->value) {
12356 found = 1;
12357 break;
12358 }
12359 curB = curB->next;
12360 }
12361 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012362 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012363 cur = cur->next;
12364 }
12365 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012366 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012367 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012368 xmlSchemaWildcardNsPtr cur;
12369 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012370 * 3.2.2 super must be a pair of not and a namespace name or
12371 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012372 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012373 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012374 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012375 if (cur->value == super->negNsSet->value)
12376 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012377 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012378 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012379 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012380 }
12381 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012382 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012383}
12384
12385/**
12386 * xmlSchemaBuildCompleteAttributeWildcard:
12387 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012388 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012389 * @completeWild: the resulting complete wildcard
12390 *
12391 * Returns -1 in case of an internal error, 0 otherwise.
12392 */
12393static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012394xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012395 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012396 xmlSchemaWildcardPtr *completeWild)
12397{
Daniel Veillard3646d642004-06-02 19:19:14 +000012398 while (attrs != NULL) {
12399 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12400 xmlSchemaAttributeGroupPtr group;
12401
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012402 group = (xmlSchemaAttributeGroupPtr) attrs;
12403 /*
12404 * Handle attribute group references.
12405 */
12406 if (group->ref != NULL) {
12407 if (group->refItem == NULL) {
12408 /*
12409 * TODO: Should we raise a warning here?
12410 */
12411 /*
12412 * The referenced attribute group definition could not
12413 * be resolved beforehand, so skip.
12414 */
12415 attrs = attrs->next;
12416 continue;
12417 } else
12418 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012419 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012420 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012421 * For every attribute group definition, an intersected wildcard
12422 * will be created (assumed that a wildcard exists on the
12423 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012424 * at all).
12425 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12426 * that the intersection will be performed only once.
12427 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012428 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12429 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012430 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012431 group->attributes, &group->attributeWildcard) == -1)
12432 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012433 }
12434 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012435 }
12436 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012437 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012438 /*
12439 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012440 *
12441 * Although the complete wildcard might not correspond to any
12442 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012443 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012444 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12445 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12446 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012447 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012448 completeWild, group->attributeWildcard) == -1)
12449 return (-1);
12450 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012451 (*completeWild)->node = group->attributeWildcard->node;
12452 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012453 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012454 }
12455 }
12456 attrs = attrs->next;
12457 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012458
12459 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012460}
12461
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012462static int
12463xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12464 int *fixed,
12465 const xmlChar **value,
12466 xmlSchemaValPtr *val)
12467{
12468 *fixed = 0;
12469 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012470 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012471 *val = NULL;
12472
12473 if (item->defValue == NULL)
12474 item = item->refDecl;
12475
12476 if (item == NULL)
12477 return (0);
12478
12479 if (item->defValue != NULL) {
12480 *value = item->defValue;
12481 if (val != 0)
12482 *val = item->defVal;
12483 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12484 *fixed = 1;
12485 return (1);
12486 }
12487 return (0);
12488}
Daniel Veillard3646d642004-06-02 19:19:14 +000012489/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012490 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012491 * @wild: the wildcard
12492 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012493 *
12494 * Validation Rule: Wildcard allows Namespace Name
12495 * (cvc-wildcard-namespace)
12496 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012497 *
12498 * Returns 1 if the given namespace matches the wildcard,
12499 * 0 otherwise.
12500 */
12501static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012502xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12503 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012504{
12505 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012506 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012507
12508 if (wild->any)
12509 return(1);
12510 else if (wild->nsSet != NULL) {
12511 xmlSchemaWildcardNsPtr cur;
12512
12513 cur = wild->nsSet;
12514 while (cur != NULL) {
12515 if (xmlStrEqual(cur->value, ns))
12516 return(1);
12517 cur = cur->next;
12518 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012519 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012520 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012521 return(1);
12522
Daniel Veillard3646d642004-06-02 19:19:14 +000012523 return(0);
12524}
12525
12526/**
12527 * xmlSchemaBuildAttributeValidation:
12528 * @ctxt: the schema parser context
12529 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012530 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012531 *
12532 * Builds the wildcard and the attribute uses on the given complex type.
12533 * Returns -1 if an internal error occurs, 0 otherwise.
12534 */
12535static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012536xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12537 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012538{
12539 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012540 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12541 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012542 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012543 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012544 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012545 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012546
Daniel Veillard01fa6152004-06-29 17:04:39 +000012547 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012548 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012549 * Complex Type Definition with complex content Schema Component.
12550 *
12551 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012552 * TODO: Add checks for absent referenced attribute declarations and
12553 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012554 */
12555 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012556 PERROR_INT("xmlSchemaBuildAttributeValidation",
12557 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012558 return (-1);
12559 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012560 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012561 PERROR_INT("xmlSchemaBuildAttributeValidation",
12562 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012563 return (-1);
12564 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012565 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012566 /*
12567 * Inherit the attribute uses of the base type.
12568 */
12569 /*
12570 * NOTE: It is allowed to "extend" the anyType complex type.
12571 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012572 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012573 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012574 for (cur = baseType->attributeUses; cur != NULL;
12575 cur = cur->next) {
12576 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012577 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12578 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012579 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012580 "building attribute uses of complexType", NULL);
12581 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012582 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012583 tmp->attr = cur->attr;
12584 tmp->next = NULL;
12585 if (type->attributeUses == NULL) {
12586 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012587 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012588 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012589 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012590 }
12591 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012592 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012593 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012594 /*
12595 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012596 */
12597 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12598 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012599 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012600 * NOTE: During the parse time, the wildcard is created on the complexType
12601 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012602 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012603 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012604 PERROR_INT("xmlSchemaBuildAttributeValidation",
12605 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012606 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012607 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012608
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012609 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12610 ((IS_ANYTYPE(baseType)) ||
12611 ((baseType != NULL) &&
12612 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12613 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012614 if (type->attributeWildcard != NULL) {
12615 /*
12616 * Union the complete wildcard with the base wildcard.
12617 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012618 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012619 baseType->attributeWildcard) == -1)
12620 return (-1);
12621 } else {
12622 /*
12623 * Just inherit the wildcard.
12624 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012625 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012626 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012627 * wildcard is shared.
12628 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012629 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012630 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012631 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012632
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012633 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12634 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012635 /*
12636 * Derivation Valid (Restriction, Complex)
12637 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012638 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012639 if (baseType->attributeWildcard == NULL) {
12640 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012641 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012642 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012643 "The type has an attribute wildcard, "
12644 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012645 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012646 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012647 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012648 } else if (xmlSchemaCheckCOSNSSubset(
12649 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012650 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012651 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012652 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012653 NULL, type, NULL,
12654 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012655 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012656 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12657 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012658 return (1);
12659 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012660 /* 4.3 Unless the {base type definition} is the ·ur-type
12661 * definition·, the complex type definition's {attribute
12662 * wildcard}'s {process contents} must be identical to or
12663 * stronger than the {base type definition}'s {attribute
12664 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012665 * than lax is stronger than skip.
12666 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012667 if ((! IS_ANYTYPE(baseType)) &&
12668 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012669 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012670 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012671 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012672 NULL, type, NULL,
12673 "The 'process contents' of the attribute wildcard is "
12674 "weaker than the one in the base type %s",
12675 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012676 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012677 return (1);
12678 }
12679 }
12680 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12681 /*
12682 * Derivation Valid (Extension)
12683 * At this point the type and the base have both, either
12684 * no wildcard or a wildcard.
12685 */
12686 if ((baseType->attributeWildcard != NULL) &&
12687 (baseType->attributeWildcard != type->attributeWildcard)) {
12688 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012689 if (xmlSchemaCheckCOSNSSubset(
12690 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012691 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012692 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012693 NULL, type, NULL,
12694 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012695 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012696 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12697 FREE_AND_NULL(str)
12698 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012699 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012700 }
12701 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012702
Daniel Veillard3646d642004-06-02 19:19:14 +000012703 /*
12704 * Gather attribute uses defined by this type.
12705 */
12706 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012707 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012708 &uses, &lastUse) == -1) {
12709 return (-1);
12710 }
12711 }
12712 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012713 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012714 * not have identical {name}s and {target namespace}s."
12715 *
12716 * For "extension" this is done further down.
12717 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012718 if ((uses != NULL) && ((type->flags &
12719 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012720 cur = uses;
12721 while (cur != NULL) {
12722 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012723 while (tmp != NULL) {
12724 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012725 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012726 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012727 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12728
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012729 xmlSchemaPAttrUseErr(pctxt,
12730 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12731 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012732 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012733 xmlSchemaFormatQName(&str,
12734 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12735 xmlSchemaGetAttrName(tmp->attr)));
12736 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012737 break;
12738 }
12739 tmp = tmp->next;
12740 }
12741 cur = cur->next;
12742 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012743 }
12744 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012745 /*
12746 * Derive by restriction.
12747 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012748 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012749 type->attributeUses = uses;
12750 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012751 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012752 const xmlChar *bEffValue;
12753 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012754
12755 cur = uses;
12756 while (cur != NULL) {
12757 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012758 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012759 base = type->attributeUses;
12760 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012761 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012762 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012763 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012764 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012765
12766 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012767
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012768 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012769 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12770 (base->attr->occurs ==
12771 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12772 /*
12773 * NOOP.
12774 */
12775 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012776 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12777 (base->attr->occurs ==
12778 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012779 /*
12780 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012781 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012782 xmlSchemaPAttrUseErr(pctxt,
12783 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12784 type, cur->attr,
12785 "The 'optional' use is inconsistent with a "
12786 "matching 'required' use of the base type",
12787 NULL);
12788 } else if ((cur->attr->occurs ==
12789 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12790 (base->attr->occurs ==
12791 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12792 /*
12793 * derivation-ok-restriction 3
12794 */
12795 xmlSchemaPCustomErr(pctxt,
12796 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12797 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012798 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012799 "attribute use '%s' of the base type is "
12800 "missing",
12801 xmlSchemaFormatQName(&str,
12802 xmlSchemaGetAttrTargetNsURI(base->attr),
12803 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012804 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012805 } else if (xmlSchemaCheckCOSSTDerivedOK(
12806 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12807
12808 /*
12809 * SPEC (2.1.2) "R's {attribute declaration}'s
12810 * {type definition} must be validly derived from
12811 * B's {type definition} given the empty set as
12812 * defined in Type Derivation OK (Simple) (§3.14.6)."
12813 */
12814 xmlSchemaPAttrUseErr(pctxt,
12815 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12816 type, cur->attr,
12817 "The attribute declaration's type "
12818 "definition is not validly derived from "
12819 "the corresponding definition in the "
12820 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012821 } else {
12822 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012823 * 2.1.3 [Definition:] Let the effective value
12824 * constraint of an attribute use be its {value
12825 * constraint}, if present, otherwise its {attribute
12826 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012827 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012828 xmlSchemaGetEffectiveValueConstraint(base->attr,
Daniel Veillard24505b02005-07-28 23:49:35 +000012829 &effFixed, &bEffValue, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012830 /*
12831 * 2.1.3 ... one of the following must be true
12832 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012833 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012834 * ·absent· or default.
12835 */
12836 if ((bEffValue != NULL) &&
12837 (effFixed == 1)) {
12838 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012839
12840 xmlSchemaGetEffectiveValueConstraint(base->attr,
Daniel Veillard24505b02005-07-28 23:49:35 +000012841 &effFixed, &rEffValue, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012842 /*
12843 * 2.1.3.2 R's ·effective value constraint· is
12844 * fixed with the same string as B's.
12845 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012846 */
12847 if ((effFixed == 0) ||
12848 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012849 xmlSchemaPAttrUseErr(pctxt,
12850 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12851 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012852 "The effective value constraint of the "
12853 "attribute use is inconsistent with "
12854 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012855 NULL);
12856 } else {
12857 /*
12858 * Override the attribute use.
12859 */
12860 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012861 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012862 } else
12863 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012864 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012865
Daniel Veillard3646d642004-06-02 19:19:14 +000012866 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012867 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012868 base = base->next;
12869 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012870
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012871 if ((!found) && (cur->attr->occurs !=
12872 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12873 /*
12874 * derivation-ok-restriction 2.2
12875 */
12876 if ((baseType->attributeWildcard == NULL) ||
12877 (xmlSchemaCheckCVCWildcardNamespace(
12878 baseType->attributeWildcard,
12879 cur->attr->targetNamespace) != 1)) {
12880 xmlSchemaPAttrUseErr(pctxt,
12881 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12882 type, cur->attr,
12883 "Neither a matching attribute use, "
12884 "nor a matching wildcard in the base type does exist",
12885 NULL);
12886 } else {
12887 /*
12888 * Add the attribute use.
12889 *
12890 * Note that this may lead to funny derivation error reports, if
12891 * multiple equal attribute uses exist; but this is not
12892 * allowed anyway, and it will be reported beforehand.
12893 */
12894 tmp = cur;
12895 if (prev != NULL)
12896 prev->next = cur->next;
12897 else
12898 uses = cur->next;
12899 cur = cur->next;
12900 tmp->next = NULL;
12901 if (type->attributeUses == NULL) {
12902 type->attributeUses = tmp;
12903 } else
12904 lastBaseUse->next = tmp;
12905 lastBaseUse = tmp;
12906
12907 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012908 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012909 }
12910 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012911 cur = cur->next;
12912 }
12913 if (uses != NULL)
12914 xmlSchemaFreeAttributeUseList(uses);
12915 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012916 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012917 /*
12918 * The spec allows only appending, and not other kinds of extensions.
12919 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012920 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012921 */
12922 if (uses != NULL) {
12923 if (type->attributeUses == NULL) {
12924 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012925 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012926 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012927 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012928 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012929 PERROR_INT("xmlSchemaBuildAttributeValidation",
12930 "no derivation method");
12931 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012932 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012933 /*
12934 * 3.4.6 -> Complex Type Definition Properties Correct
12935 */
12936 if (type->attributeUses != NULL) {
12937 cur = type->attributeUses;
12938 prev = NULL;
12939 while (cur != NULL) {
12940 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012941 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012942 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012943 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012944 * Note that this was already done for "restriction" and types derived from
12945 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012946 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012947 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12948 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012949 while (tmp != NULL) {
12950 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012951 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012952 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012953 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012954
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012955 xmlSchemaPAttrUseErr(pctxt,
12956 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12957 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012958 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012959 break;
12960 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012961 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012962 }
12963 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012964 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012965 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012966 * not have {type definition}s which are or are derived from ID.
12967 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012968 if ((cur->attr->subtypes != NULL) &&
12969 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12970 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012971 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012972 xmlSchemaPAttrUseErr(pctxt,
12973 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12974 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012975 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012976 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012977 NULL);
12978 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012979 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012980 id = cur;
12981 }
12982 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012983 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012984 * stage is to be able to catch dublicate attribute uses. So we had to keep
12985 * prohibited uses in the list as well.
12986 */
12987 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12988 tmp = cur;
12989 if (prev == NULL)
12990 type->attributeUses = cur->next;
12991 else
12992 prev->next = cur->next;
12993 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012994 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012995 } else {
12996 prev = cur;
12997 cur = cur->next;
12998 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012999 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013000 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013001 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013002 * TODO: This check should be removed if we are 100% sure of
13003 * the base type attribute uses already being built.
13004 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013005 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013006 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013007 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013008 PERROR_INT("xmlSchemaBuildAttributeValidation",
13009 "attribute uses not builded on base type");
13010 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013011 return (0);
13012}
13013
13014/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013015 * xmlSchemaTypeFinalContains:
13016 * @schema: the schema
13017 * @type: the type definition
13018 * @final: the final
13019 *
13020 * Evaluates if a type definition contains the given "final".
13021 * This does take "finalDefault" into account as well.
13022 *
13023 * Returns 1 if the type does containt the given "final",
13024 * 0 otherwise.
13025 */
13026static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013027xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013028{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013029 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013030 return (0);
13031 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013032 return (1);
13033 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013034 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013035}
13036
13037/**
13038 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13039 * @type: the Union Simple Type
13040 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013041 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013042 * returns NULL otherwise.
13043 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013044static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013045xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13046{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013047 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013048 if (type->memberTypes != NULL)
13049 return (type->memberTypes);
13050 else
13051 type = type->baseType;
13052 }
13053 return (NULL);
13054}
13055
13056/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013057 * xmlSchemaGetParticleTotalRangeMin:
13058 * @particle: the particle
13059 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013060 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013061 * (all and sequence) + (choice)
13062 *
13063 * Returns the minimun Effective Total Range.
13064 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013065static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013066xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013067{
13068 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013069 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013070 return (0);
13071 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013072 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013073 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013074 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013075
13076 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013077 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013078 while (part != NULL) {
13079 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13080 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013081 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013082 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013083 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013084 if (cur == 0)
13085 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013086 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013087 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013088 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013089 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013090 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013091 } else {
13092 /* <all> and <sequence> */
13093 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013094 xmlSchemaParticlePtr part =
13095 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013096
13097 if (part == NULL)
13098 return (0);
13099 do {
13100 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13101 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013102 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013103 else
13104 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013105 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013106 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013107 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013108 }
13109}
13110
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013111/**
13112 * xmlSchemaGetParticleTotalRangeMax:
13113 * @particle: the particle
13114 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013115 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013116 * (all and sequence) + (choice)
13117 *
13118 * Returns the maximum Effective Total Range.
13119 */
13120static int
13121xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13122{
13123 if ((particle->children == NULL) ||
13124 (particle->children->children == NULL))
13125 return (0);
13126 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13127 int max = -1, cur;
13128 xmlSchemaParticlePtr part =
13129 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013130
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013131 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13132 if (part->children == NULL)
13133 continue;
13134 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13135 (part->children->type == XML_SCHEMA_TYPE_ANY))
13136 cur = part->maxOccurs;
13137 else
13138 cur = xmlSchemaGetParticleTotalRangeMax(part);
13139 if (cur == UNBOUNDED)
13140 return (UNBOUNDED);
13141 if ((max < cur) || (max == -1))
13142 max = cur;
13143 }
13144 /* TODO: Handle overflows? */
13145 return (particle->maxOccurs * max);
13146 } else {
13147 /* <all> and <sequence> */
13148 int sum = 0, cur;
13149 xmlSchemaParticlePtr part =
13150 (xmlSchemaParticlePtr) particle->children->children;
13151
13152 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13153 if (part->children == NULL)
13154 continue;
13155 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13156 (part->children->type == XML_SCHEMA_TYPE_ANY))
13157 cur = part->maxOccurs;
13158 else
13159 cur = xmlSchemaGetParticleTotalRangeMax(part);
13160 if (cur == UNBOUNDED)
13161 return (UNBOUNDED);
13162 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13163 return (UNBOUNDED);
13164 sum += cur;
13165 }
13166 /* TODO: Handle overflows? */
13167 return (particle->maxOccurs * sum);
13168 }
13169}
13170
13171/**
13172 * xmlSchemaIsParticleEmptiable:
13173 * @particle: the particle
13174 *
13175 * Schema Component Constraint: Particle Emptiable
13176 * Checks whether the given particle is emptiable.
13177 *
13178 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013179 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013180static int
13181xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13182{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013183 /*
13184 * SPEC (1) "Its {min occurs} is 0."
13185 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013186 if ((particle == NULL) || (particle->minOccurs == 0) ||
13187 (particle->children == NULL))
13188 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013189 /*
13190 * SPEC (2) "Its {term} is a group and the minimum part of the
13191 * effective total range of that group, [...] is 0."
13192 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013193 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013194 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013195 return (1);
13196 }
13197 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013198}
13199
13200/**
13201 * xmlSchemaCheckCOSSTDerivedOK:
13202 * @type: the derived simple type definition
13203 * @baseType: the base type definition
13204 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013205 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013206 * Type Derivation OK (Simple) (cos-st-derived-OK)
13207 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013208 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013209 * derived from @baseType.
13210 *
13211 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013212 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013213static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013214xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13215 xmlSchemaTypePtr baseType,
13216 int subset)
13217{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013218 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013219 * 1 They are the same type definition.
13220 * TODO: The identy check might have to be more complex than this.
13221 */
13222 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013223 return (0);
13224 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013225 * 2.1 restriction is not in the subset, or in the {final}
13226 * of its own {base type definition};
13227 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013228 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013229 (xmlSchemaTypeFinalContains(type->baseType,
13230 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13231 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013232 }
13233 /* 2.2 */
13234 if (type->baseType == baseType) {
13235 /*
13236 * 2.2.1 D's ·base type definition· is B.
13237 */
13238 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013239 }
13240 /*
13241 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13242 * and is validly derived from B given the subset, as defined by this
13243 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013244 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013245 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013246 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013247 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013248 return (0);
13249 }
13250 /*
13251 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013252 * definition·.
13253 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013254 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013255 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013256 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013257 }
13258 /*
13259 * 2.2.4 B's {variety} is union and D is validly derived from a type
13260 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013261 * defined by this constraint.
13262 *
13263 * NOTE: This seems not to involve built-in types, since there is no
13264 * built-in Union Simple Type.
13265 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013266 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013267 xmlSchemaTypeLinkPtr cur;
13268
13269 cur = baseType->memberTypes;
13270 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013271 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013272 return (0);
13273 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013274 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013275 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013276
Daniel Veillard01fa6152004-06-29 17:04:39 +000013277 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13278}
13279
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013280/**
13281 * xmlSchemaCheckTypeDefCircularInternal:
13282 * @pctxt: the schema parser context
13283 * @ctxtType: the type definition
13284 * @ancestor: an ancestor of @ctxtType
13285 *
13286 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013287 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013288 *
13289 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13290 * circular, 0 otherwise.
13291 */
13292static int
13293xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13294 xmlSchemaTypePtr ctxtType,
13295 xmlSchemaTypePtr ancestor)
13296{
13297 int ret;
13298
13299 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13300 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013301
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013302 if (ctxtType == ancestor) {
13303 xmlSchemaPCustomErr(pctxt,
13304 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13305 NULL, ctxtType, GET_NODE(ctxtType),
13306 "The definition is circular", NULL);
13307 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13308 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013309 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13310 /*
13311 * Avoid inifinite recursion on circular types not yet checked.
13312 */
13313 return (0);
13314 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013315 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13316 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13317 ancestor->baseType);
13318 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13319 return (ret);
13320}
13321
13322/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013323 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013324 * @item: the complex/simple type definition
13325 * @ctxt: the parser context
13326 * @name: the name
13327 *
13328 * Checks for circular type definitions.
13329 */
13330static void
13331xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013332 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013333 const xmlChar * name ATTRIBUTE_UNUSED)
13334{
13335 if ((item == NULL) ||
13336 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13337 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13338 return;
13339 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13340
13341}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013342
13343/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013344 * xmlSchemaResolveTypeDefs:
13345 * @item: the complex/simple type definition
13346 * @ctxt: the parser context
13347 * @name: the name
13348 *
13349 * Checks for circular type definitions.
13350 */
13351static void
13352xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013353 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013354 const xmlChar * name ATTRIBUTE_UNUSED)
13355{
13356 if (typeDef == NULL)
13357 return;
13358
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013359 /*
13360 * Resolve the base type.
13361 */
13362 if (typeDef->baseType == NULL) {
13363 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13364 typeDef->base, typeDef->baseNs);
13365 if (typeDef->baseType == NULL) {
13366 xmlSchemaPResCompAttrErr(ctxt,
13367 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013368 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013369 "base", typeDef->base, typeDef->baseNs,
13370 XML_SCHEMA_TYPE_SIMPLE, NULL);
13371 return;
13372 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013373 }
13374 if (IS_SIMPLE_TYPE(typeDef)) {
13375 if (VARIETY_UNION(typeDef)) {
13376 /*
13377 * Resolve the memberTypes.
13378 */
13379 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13380 return;
13381 } else if (VARIETY_LIST(typeDef)) {
13382 /*
13383 * Resolve the itemType.
13384 */
13385 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13386 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13387 typeDef->ref, typeDef->refNs);
13388 if ((typeDef->subtypes == NULL) ||
13389 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13390 typeDef->subtypes = NULL;
13391 xmlSchemaPResCompAttrErr(ctxt,
13392 XML_SCHEMAP_SRC_RESOLVE,
13393 typeDef, typeDef->node,
13394 "itemType", typeDef->ref, typeDef->refNs,
13395 XML_SCHEMA_TYPE_SIMPLE, NULL);
13396 }
13397 }
13398 return;
13399 }
13400 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013401}
13402
13403
13404
13405/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013406 * xmlSchemaCheckSTPropsCorrect:
13407 * @ctxt: the schema parser context
13408 * @type: the simple type definition
13409 *
13410 * Checks st-props-correct.
13411 *
13412 * Returns 0 if the properties are correct,
13413 * if not, a positive error code and -1 on internal
13414 * errors.
13415 */
13416static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013417xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013418 xmlSchemaTypePtr type)
13419{
13420 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13421 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013422 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013423
Daniel Veillardc0826a72004-08-10 14:17:33 +000013424 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013425 /*
13426 * Schema Component Constraint: Simple Type Definition Properties Correct
13427 *
13428 * NOTE: This is somehow redundant, since we actually built a simple type
13429 * to have all the needed information; this acts as an self test.
13430 */
13431 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13432 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013433 /* Base type: If the datatype has been ·derived· by ·restriction·
13434 * then the Simple Type Definition component from which it is ·derived·,
13435 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013436 */
13437 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013438 /*
13439 * TODO: Think about: "modulo the impact of Missing
13440 * Sub-components (§5.3)."
13441 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013442 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013443 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013444 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013445 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013446 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013447
Daniel Veillard01fa6152004-06-29 17:04:39 +000013448 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013449 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013450 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013451 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013452 NULL, type, NULL,
13453 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013454 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013455 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013456 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13457 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013458 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13459 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13460 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013461 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013462 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013463 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013464 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013465 "the simple ur-type definition as base type, not '%s'",
13466 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013467 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013468 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13469 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013470 /*
13471 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013472 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013473 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13474 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013475 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013476 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013477 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013478 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013479 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13480 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013481 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013482
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013483 /*
13484 * 3 The {final} of the {base type definition} must not contain restriction.
13485 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013486 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013487 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13488 xmlSchemaPCustomErr(ctxt,
13489 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013491 "The 'final' of its base type '%s' must not contain "
13492 "'restriction'",
13493 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013494 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013495 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013496 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013497
13498 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013499 * 2 All simple type definitions must be derived ultimately from the ·simple
13500 * ur-type definition (so· circular definitions are disallowed). That is, it
13501 * must be possible to reach a built-in primitive datatype or the ·simple
13502 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013503 *
13504 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013505 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013506 return (0);
13507}
13508
13509/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013510 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013511 * @ctxt: the schema parser context
13512 * @type: the simple type definition
13513 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013514 * Schema Component Constraint:
13515 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13516
13517 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013518 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013519 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013520 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013521 * a positive error code otherwise.
13522 */
13523static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013524xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013525 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013526{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013527 xmlChar *str = NULL;
13528
Daniel Veillard01fa6152004-06-29 17:04:39 +000013529 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013530 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13531 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013532 return (-1);
13533 }
13534
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013535 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013536 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013537 /*
13538 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013539 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540 */
13541 if (! VARIETY_ATOMIC(type->baseType)) {
13542 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013543 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013544 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013545 "The base type '%s' is not an atomic simple type",
13546 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013547 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013548 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13549 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013550 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013551 * restriction.
13552 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013553 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013554 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013555 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013556 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013557 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013558 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013559 "The final of its base type '%s' must not contain 'restriction'",
13560 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013561 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013562 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13563 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013564
13565 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013566 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013567 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013568 * Primitive datatypes.
13569 */
13570 if (type->facets != NULL) {
13571 xmlSchemaFacetPtr facet;
13572 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013573
Daniel Veillard01fa6152004-06-29 17:04:39 +000013574 primitive = xmlSchemaGetPrimitiveType(type);
13575 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013576 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13577 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013578 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013579 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013580 facet = type->facets;
13581 do {
13582 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013583 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013584 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013585 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013586 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013587 }
13588 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013589 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013590 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013591 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013592 }
13593 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013594 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13595 * of the {base type definition} (call this BF),then the DF's {value}
13596 * must be a valid restriction of BF's {value} as defined in
13597 * [XML Schemas: Datatypes]."
13598 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013599 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013600 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013602 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013603 xmlSchemaTypePtr itemType = NULL;
13604
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013605 itemType = type->subtypes;
13606 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013607 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13608 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013609 return (-1);
13610 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013611 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013612 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013613 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013614 * 2.1 The {item type definition} must have a {variety} of atomic or
13615 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013616 * must be atomic).
13617 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013618 if ((! VARIETY_ATOMIC(itemType)) &&
13619 (! VARIETY_UNION(itemType))) {
13620 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013621 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013622 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013623 "The item type '%s' does not have a variety of atomic or union",
13624 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013625 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013626 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013627 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013628 xmlSchemaTypeLinkPtr member;
13629
13630 member = itemType->memberTypes;
13631 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013632 if (! VARIETY_ATOMIC(member->type)) {
13633 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013634 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013635 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013636 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013637 "member type '%s' of this item type is not atomic",
13638 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013639 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013640 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13641 }
13642 member = member->next;
13643 }
13644 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013645
13646 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013647 xmlSchemaFacetPtr facet;
13648 /*
13649 * This is the case if we have: <simpleType><list ..
13650 */
13651 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013652 * 2.3.1
13653 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013654 * contain list.
13655 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013656 if (xmlSchemaTypeFinalContains(itemType,
13657 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13658 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013659 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013660 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013661 "The final of its item type '%s' must not contain 'list'",
13662 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013663 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013664 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13665 }
13666 /*
13667 * 2.3.1.2 The {facets} must only contain the whiteSpace
13668 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013669 * OPTIMIZE TODO: the S4S already disallows any facet
13670 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013671 */
13672 if (type->facets != NULL) {
13673 facet = type->facets;
13674 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013675 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013676 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013677 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013678 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013679 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13680 }
13681 facet = facet->next;
13682 } while (facet != NULL);
13683 }
13684 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013685 * MAYBE TODO: (Hmm, not really) Datatypes states:
13686 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13687 * whose ·lexical space· allows space (such as string or anyURI)or
13688 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013689 * ·lexical space· allows space.
13690 */
13691 } else {
13692 /*
13693 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013694 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013695 */
13696 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013697 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013698 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13699 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013700 if (! VARIETY_LIST(type->baseType)) {
13701 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013702 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013703 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013704 "The base type '%s' must be a list type",
13705 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013706 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013707 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13708 }
13709 /*
13710 * 2.3.2.2 The {final} of the {base type definition} must not
13711 * contain restriction.
13712 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013713 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013714 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013715 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013716 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013717 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013718 "The 'final' of the base type '%s' must not contain 'restriction'",
13719 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013720 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013721 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13722 }
13723 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013724 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013725 * from the {base type definition}'s {item type definition} given
13726 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13727 */
13728 {
13729 xmlSchemaTypePtr baseItemType;
13730
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013731 baseItemType = type->baseType->subtypes;
13732 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013733 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13734 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013735 return (-1);
13736 }
13737 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013738 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13739 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013740 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013741 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013742 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013743 NULL, type, NULL,
13744 "The item type '%s' is not validly derived from "
13745 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013746 xmlSchemaGetComponentQName(&str, itemType),
13747 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13748 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013749
13750 FREE_AND_NULL(str)
13751 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013752 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013753 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13754 }
13755 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013756
Daniel Veillard01fa6152004-06-29 17:04:39 +000013757 if (type->facets != NULL) {
13758 xmlSchemaFacetPtr facet;
13759 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013760 /*
13761 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013762 * and enumeration facet components are allowed among the {facets}.
13763 */
13764 facet = type->facets;
13765 do {
13766 switch (facet->type) {
13767 case XML_SCHEMA_FACET_LENGTH:
13768 case XML_SCHEMA_FACET_MINLENGTH:
13769 case XML_SCHEMA_FACET_MAXLENGTH:
13770 case XML_SCHEMA_FACET_WHITESPACE:
13771 /*
13772 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013773 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013774 */
13775 case XML_SCHEMA_FACET_PATTERN:
13776 case XML_SCHEMA_FACET_ENUMERATION:
13777 break;
13778 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013779 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013780 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013781 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013782 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013783 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013784 * invalid facets.
13785 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013786 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013788 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013789 facet = facet->next;
13790 } while (facet != NULL);
13791 if (ok == 0)
13792 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13793 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013794 * SPEC (2.3.2.5) (same as 1.3.2)
13795 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013796 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013797 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013798 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013799 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013800 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013801 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013802 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013803 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013804 * atomic or list.
13805 */
13806 xmlSchemaTypeLinkPtr member;
13807
13808 member = type->memberTypes;
13809 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013810 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013811 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013812
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013813 if ((! VARIETY_ATOMIC(member->type)) &&
13814 (! VARIETY_LIST(member->type))) {
13815 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013816 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013817 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013818 "The member type '%s' is neither an atomic, nor a list type",
13819 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013820 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013821 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13822 }
13823 member = member->next;
13824 }
13825 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013826 * 3.3.1 If the {base type definition} is the ·simple ur-type
13827 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013828 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013829 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013830 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013831 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013832 * {final} which does not contain union.
13833 */
13834 member = type->memberTypes;
13835 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013836 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013837 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013838 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013839 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013840 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013841 "The 'final' of member type '%s' contains 'union'",
13842 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013843 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013844 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13845 }
13846 member = member->next;
13847 }
13848 /*
13849 * 3.3.1.2 The {facets} must be empty.
13850 */
13851 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013852 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013853 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013854 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013855 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013856 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13857 }
13858 } else {
13859 /*
13860 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013861 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013862 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013863 if (! VARIETY_UNION(type->baseType)) {
13864 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013865 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013866 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013867 "The base type '%s' is not a union type",
13868 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013869 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013870 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13871 }
13872 /*
13873 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13874 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013875 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013876 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013877 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013878 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013879 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013880 "The 'final' of its base type '%s' must not contain 'restriction'",
13881 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013882 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013883 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13884 }
13885 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013886 * 3.3.2.3 The {member type definitions}, in order, must be validly
13887 * derived from the corresponding type definitions in the {base
13888 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013889 * as defined in Type Derivation OK (Simple) (§3.14.6).
13890 */
13891 {
13892 xmlSchemaTypeLinkPtr baseMember;
13893
13894 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013895 * OPTIMIZE: if the type is restricting, it has no local defined
13896 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013897 * thus a check for equality can be skipped.
13898 */
13899 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013900 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013901 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013902 * types of it's base type. This check seems not necessary with
13903 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013904 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013905 */
13906 if (type->memberTypes != NULL) {
13907 member = type->memberTypes;
13908 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013909 if ((member == NULL) && (baseMember != NULL)) {
13910 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13911 "different number of member types in base");
13912 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013913 while (member != NULL) {
13914 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013915 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13916 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013917 }
13918 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013919 (xmlSchemaCheckCOSSTDerivedOK(
13920 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013921 xmlChar *strBMT = NULL, *strBT = NULL;
13922
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013923 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013924 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13925 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013926 "The member type %s is not validly "
13927 "derived from its corresponding member "
13928 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013929 xmlSchemaGetComponentQName(&str, member->type),
13930 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13931 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013932 FREE_AND_NULL(str)
13933 FREE_AND_NULL(strBMT)
13934 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013935 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013936 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013937 member = member->next;
13938 baseMember = baseMember->next;
13939 }
13940 }
13941 }
13942 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013943 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013944 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013945 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013946 if (type->facets != NULL) {
13947 xmlSchemaFacetPtr facet;
13948 int ok = 1;
13949
13950 facet = type->facets;
13951 do {
13952 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13953 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013954 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013955 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013956 NULL, type, facet);
13957 ok = 0;
13958 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013959 facet = facet->next;
13960 } while (facet != NULL);
13961 if (ok == 0)
13962 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013963
Daniel Veillard01fa6152004-06-29 17:04:39 +000013964 }
13965 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013966 * SPEC (3.3.2.5) (same as 1.3.2)
13967 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013968 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013969 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013970 */
13971 }
13972 }
13973
13974 return (0);
13975}
13976
13977/**
13978 * xmlSchemaCheckSRCSimpleType:
13979 * @ctxt: the schema parser context
13980 * @type: the simple type definition
13981 *
13982 * Checks crc-simple-type constraints.
13983 *
13984 * Returns 0 if the constraints are satisfied,
13985 * if not a positive error code and -1 on internal
13986 * errors.
13987 */
13988static int
13989xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13990 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013991{
13992 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013993 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013994 * must satisfy the conditions set out in Constraints on Simple Type
13995 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013996 */
13997 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13998 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13999 /*
14000 * TODO: Removed this, since it got annoying to get an
14001 * extra error report, if anything failed until now.
14002 * Enable this if needed.
14003 */
14004 /*
14005 xmlSchemaPErr(ctxt, type->node,
14006 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014007 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014008 "on simple type definitions.\n",
14009 type->name, NULL);
14010 */
14011 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
14012 }
14013
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014014 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014015 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014016 * src-simple-type.2 If the <restriction> alternative is chosen,
14017 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000014018 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014019 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014020 /*
14021 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014022 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014023 */
14024 } else if (VARIETY_LIST(type)) {
14025 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
14026 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000014027 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014028 *
14029 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014030 */
14031 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014032 xmlSchemaTypeLinkPtr member;
14033 xmlSchemaTypePtr ancestor, anySimpleType;
14034
14035 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14036
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014037 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14038 * the <union> alternative is chosen, there must not be any entries
14039 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000014040 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014041 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014042 member = type->memberTypes;
14043 while (member != NULL) {
14044 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014045 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014046 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014047 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014048 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014049 NULL, type, NULL,
14050 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014051 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014052 }
14053 if (IS_NOT_TYPEFIXED(ancestor))
14054 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014055 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014056 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014057 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014058 * type as item type, which in turn has a list ST as member
14059 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000014060 * was not yet performed.
14061 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014063
Daniel Veillard01fa6152004-06-29 17:04:39 +000014064 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014065 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014066 member = member->next;
14067 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014068 }
14069
14070 return (0);
14071}
14072
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014073static int
14074xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14075{
14076 if (ctxt->vctxt == NULL) {
14077 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14078 if (ctxt->vctxt == NULL) {
14079 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014080 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014081 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014082 "failed to create a temp. validation context.\n",
14083 NULL, NULL);
14084 return (-1);
14085 }
14086 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014087 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014088 }
14089 return (0);
14090}
14091
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014092static int
14093xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14094 xmlNodePtr node,
14095 xmlSchemaTypePtr type,
14096 const xmlChar *value,
14097 xmlSchemaValPtr *retVal,
14098 int fireErrors,
14099 int normalize,
14100 int isNormalized);
14101
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014102/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014103 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014104 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014105 * @type: the simple type definition
14106 * @value: the default value
14107 * @node: an optional node (the holder of the value)
14108 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014109 * Schema Component Constraint: Element Default Valid (Immediate)
14110 * (cos-valid-default)
14111 * This will be used by the parser only. For the validator there's
14112 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014113 *
14114 * Returns 0 if the constraints are satisfied,
14115 * if not, a positive error code and -1 on internal
14116 * errors.
14117 */
14118static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014119xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14120 xmlNodePtr node,
14121 xmlSchemaTypePtr type,
14122 const xmlChar *value,
14123 xmlSchemaValPtr *val)
14124{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014125 int ret = 0;
14126
14127 /*
14128 * cos-valid-default:
14129 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014130 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014131 * definition the appropriate case among the following must be true:
14132 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014133 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014134 /*
14135 * Complex type.
14136 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014137 * SPEC (2.1) "its {content type} must be a simple type definition
14138 * or mixed."
14139 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014140 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014141 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014142 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014143 if ((! HAS_SIMPLE_CONTENT(type)) &&
14144 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14145 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014146 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014147 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014148 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014149 "For a string to be a valid default, the type definition "
14150 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014151 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014152 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14153 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014154 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014155 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014156 * 1 If the type definition is a simple type definition, then the string
14157 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014158 * Valid (§3.14.4).
14159 *
14160 * AND
14161 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014162 * 2.2.1 If the {content type} is a simple type definition, then the
14163 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014164 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014165 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014166 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014167 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14168 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014169 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014170 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14171 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014172 else
14173 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014175 if (ret < 0) {
14176 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14177 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014178 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014179
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014180 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014181}
14182
14183/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014184 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014185 * @ctxt: the schema parser context
14186 * @type: the complex type definition
14187 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014188 *.(4.6) Constraints on Complex Type Definition Schema Components
14189 * Schema Component Constraint:
14190 * Complex Type Definition Properties Correct (ct-props-correct)
14191 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014192 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014193 * Returns 0 if the constraints are satisfied, a positive
14194 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014195 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014196static int
14197xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14198 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014199{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014200 /*
14201 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14202 *
14203 * SPEC (1) "The values of the properties of a complex type definition must
14204 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014205 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014206 * Sub-components (§5.3)."
14207 */
14208 if ((type->baseType != NULL) &&
14209 (IS_SIMPLE_TYPE(type->baseType)) &&
14210 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14211 /*
14212 * SPEC (2) "If the {base type definition} is a simple type definition,
14213 * the {derivation method} must be extension."
14214 */
14215 xmlSchemaPCustomErr(pctxt,
14216 XML_SCHEMAP_SRC_CT_1,
14217 NULL, type, NULL,
14218 "If the base type is a simple type, the derivation method must be "
14219 "'extension'", NULL);
14220 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014221 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014222 /*
14223 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14224 * definition·. That is, it must be possible to reach the ·ur-type
14225 * definition by repeatedly following the {base type definition}."
14226 *
14227 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14228 *
14229 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014230 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014231 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14232 * must not have {type definition}s which are or are derived from ID."
14233 *
14234 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14235 */
14236 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014237}
14238
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014239static int
14240xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14241 xmlSchemaTypePtr typeB)
14242{
14243 /*
14244 * TODO: This should implement component-identity
14245 * in the future.
14246 */
14247 if ((typeA == NULL) || (typeB == NULL))
14248 return (0);
14249 return (typeA == typeB);
14250}
14251
14252/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014253 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014254 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014255 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014256 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014257 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014258 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014259 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014260 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14261 *
14262 * STATUS: completed
14263 *
14264 * Returns 0 if the constraints are satisfied, or 1
14265 * if not.
14266 */
14267static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014268xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014269 xmlSchemaTypePtr baseType,
14270 int set)
14271{
14272 int equal = xmlSchemaAreEqualTypes(type, baseType);
14273 /* TODO: Error codes. */
14274 /*
14275 * SPEC "For a complex type definition (call it D, for derived)
14276 * to be validly derived from a type definition (call this
14277 * B, for base) given a subset of {extension, restriction}
14278 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014279 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014280 if (! equal) {
14281 /*
14282 * SPEC (1) "If B and D are not the same type definition, then the
14283 * {derivation method} of D must not be in the subset."
14284 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014285 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014286 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014287 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014288 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014289 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014290 } else {
14291 /*
14292 * SPEC (2.1) "B and D must be the same type definition."
14293 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014294 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014295 }
14296 /*
14297 * SPEC (2.2) "B must be D's {base type definition}."
14298 */
14299 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014300 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014301 /*
14302 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14303 * definition·."
14304 */
14305 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014306 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014307
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014308 if (IS_COMPLEX_TYPE(type->baseType)) {
14309 /*
14310 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14311 * must be validly derived from B given the subset as defined by this
14312 * constraint."
14313 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014314 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014315 baseType, set));
14316 } else {
14317 /*
14318 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14319 * must be validly derived from B given the subset as defined in Type
14320 * Derivation OK (Simple) (§3.14.6).
14321 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014322 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14323 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014324}
14325
14326/**
14327 * xmlSchemaCheckCOSDerivedOK:
14328 * @type: the derived simple type definition
14329 * @baseType: the base type definition
14330 *
14331 * Calls:
14332 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014333 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014334 * Checks wheter @type can be validly derived from @baseType.
14335 *
14336 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014337 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014338static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014339xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014340 xmlSchemaTypePtr baseType,
14341 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014342{
14343 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014344 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014345 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014346 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014347}
14348
William M. Brack2f2a6632004-08-20 23:09:47 +000014349/**
14350 * xmlSchemaCheckCOSCTExtends:
14351 * @ctxt: the schema parser context
14352 * @type: the complex type definition
14353 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014354 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014355 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014356 * Derivation Valid (Extension) (cos-ct-extends)
14357 *
14358 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014359 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014360 * (1.5)
14361 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014362 *
14363 * Returns 0 if the constraints are satisfied, a positive
14364 * error code if not and -1 if an internal error occured.
14365 */
14366static int
14367xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14368 xmlSchemaTypePtr type)
14369{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014370 xmlSchemaTypePtr base = type->baseType;
14371 /*
14372 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14373 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014374 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014375 /*
14376 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014377 * then all of the following must be true:"
14378 */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000014379 if (IS_COMPLEX_TYPE(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014380 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014381 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014382 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014383 */
14384 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14385 xmlSchemaPCustomErr(ctxt,
14386 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14387 NULL, type, NULL,
14388 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014389 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014390 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14391 }
14392 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014393 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014394 * uses}
14395 * of the complex type definition itself, that is, for every attribute
14396 * use in the {attribute uses} of the {base type definition}, there
14397 * must be an attribute use in the {attribute uses} of the complex
14398 * type definition itself whose {attribute declaration} has the same
14399 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014400 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014401 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014402 * NOTE (1.2): This will be already satisfied by the way the attribute
14403 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14404 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014405 */
14406
14407 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014408 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14409 * definition must also have one, and the base type definition's
14410 * {attribute wildcard}'s {namespace constraint} must be a subset
14411 * of the complex type definition's {attribute wildcard}'s {namespace
14412 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014413 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014414 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014415 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014416 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014417 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014418 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014419 if ((type->contentTypeDef != NULL) &&
14420 (type->contentTypeDef == base->contentTypeDef)) {
14421 /*
14422 * SPEC (1.4.1) "The {content type} of the {base type definition}
14423 * and the {content type} of the complex type definition itself
14424 * must be the same simple type definition"
14425 * PASS
14426 */
14427 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14428 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14429 /*
14430 * SPEC (1.4.2) "The {content type} of both the {base type
14431 * definition} and the complex type definition itself must
14432 * be empty."
14433 * PASS
14434 */
14435 } else {
14436 /*
14437 * SPEC (1.4.3) "All of the following must be true:"
14438 */
14439 if (type->subtypes == NULL) {
14440 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014441 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014442 * definition itself must specify a particle.
14443 */
14444 xmlSchemaPCustomErr(ctxt,
14445 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14446 NULL, type, NULL,
14447 "The content type must specify a particle", NULL);
14448 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14449 }
14450 /*
14451 * SPEC (1.4.3.2) "One of the following must be true:"
14452 */
14453 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14454 /*
14455 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14456 * definition} must be empty.
14457 * PASS
14458 */
14459 } else {
14460 /*
14461 * SPEC (1.4.3.2.2) "All of the following must be true:"
14462 */
14463 if ((type->contentType != base->contentType) ||
14464 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14465 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14466 /*
14467 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14468 * or both must be element-only."
14469 */
14470 xmlSchemaPCustomErr(ctxt,
14471 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14472 NULL, type, NULL,
14473 "The content type of both, the type and its base "
14474 "type, must either 'mixed' or 'element-only'", NULL);
14475 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014476 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014477 /*
14478 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14479 * complex type definition must be a ·valid extension·
14480 * of the {base type definition}'s particle, as defined
14481 * in Particle Valid (Extension) (§3.9.6)."
14482 *
14483 * NOTE that we won't check "Particle Valid (Extension)",
14484 * since it is ensured by the derivation process in
14485 * xmlSchemaTypeFixup(). We need to implement this when heading
14486 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014487 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014488 }
14489 /*
14490 * TODO (1.5)
14491 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014492 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014493 } else {
14494 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014495 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014496 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014497 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014498 if (type->contentTypeDef != base) {
14499 /*
14500 * SPEC (2.1) "The {content type} must be the same simple type
14501 * definition."
14502 */
14503 xmlSchemaPCustomErr(ctxt,
14504 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14505 NULL, type, NULL,
14506 "The content type must be the simple base type", NULL);
14507 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14508 }
14509 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14510 /*
14511 * SPEC (2.2) "The {final} of the {base type definition} must not
14512 * contain extension"
14513 * NOTE that this is the same as (1.1).
14514 */
14515 xmlSchemaPCustomErr(ctxt,
14516 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14517 NULL, type, NULL,
14518 "The 'final' of the base type definition "
14519 "contains 'extension'", NULL);
14520 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014521 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014522 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014523 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014524}
14525
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014526/**
14527 * xmlSchemaCheckDerivationOKRestriction:
14528 * @ctxt: the schema parser context
14529 * @type: the complex type definition
14530 *
14531 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014532 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014533 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14534 *
14535 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014536 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014537 * (5.4.2), (5.2.2.1)
14538 *
14539 * Returns 0 if the constraints are satisfied, a positive
14540 * error code if not and -1 if an internal error occured.
14541 */
14542static int
14543xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14544 xmlSchemaTypePtr type)
14545{
14546 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014547
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014548 /*
14549 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14550 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014551 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014552 base = type->baseType;
14553 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14554 /*
14555 * SPEC (1) "The {base type definition} must be a complex type
14556 * definition whose {final} does not contain restriction."
14557 */
14558 xmlSchemaPCustomErr(ctxt,
14559 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14560 NULL, type, NULL,
14561 "The 'final' of the base type definition "
14562 "contains 'restriction'", NULL);
14563 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14564 }
14565 /*
14566 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14567 *
14568 * SPEC (5) "One of the following must be true:"
14569 */
14570 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14571 /*
14572 * SPEC (5.1) "The {base type definition} must be the
14573 * ·ur-type definition·."
14574 * PASS
14575 */
14576 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14577 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14578 /*
14579 * SPEC (5.2.1) "The {content type} of the complex type definition
14580 * must be a simple type definition"
14581 *
14582 * SPEC (5.2.2) "One of the following must be true:"
14583 */
14584 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14585 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14586 /*
14587 * SPEC (5.2.2.1) "The {content type} of the {base type
14588 * definition} must be a simple type definition from which
14589 * the {content type} is validly derived given the empty
14590 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14591 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014592 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014593 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14594 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014595 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014596 /*
14597 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14598 * and have a particle which is ·emptiable· as defined in
14599 * Particle Emptiable (§3.9.6)."
14600 * PASS
14601 */
14602 } else {
14603 xmlSchemaPCustomErr(ctxt,
14604 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14605 NULL, type, NULL,
14606 "The content type of the base type must be either "
14607 "a simple type or 'mixed' and an emptiable particle", NULL);
14608 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14609 }
14610 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14611 /*
14612 * SPEC (5.3.1) "The {content type} of the complex type itself must
14613 * be empty"
14614 */
14615 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14616 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014617 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014618 * definition} must also be empty."
14619 * PASS
14620 */
14621 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14622 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14623 xmlSchemaIsParticleEmptiable(
14624 (xmlSchemaParticlePtr) base->subtypes)) {
14625 /*
14626 * SPEC (5.3.2.2) "The {content type} of the {base type
14627 * definition} must be elementOnly or mixed and have a particle
14628 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14629 * PASS
14630 */
14631 } else {
14632 xmlSchemaPCustomErr(ctxt,
14633 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14634 NULL, type, NULL,
14635 "The content type of the base type must be either "
14636 "empty or 'mixed' (or 'elements-only') and an emptiable "
14637 "particle", NULL);
14638 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14639 }
14640 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014641 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014642 /*
14643 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14644 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014645 */
14646 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14647 /*
14648 * SPEC (5.4.1.2) "The {content type} of the complex type
14649 * definition itself and of the {base type definition} must be
14650 * mixed"
14651 */
14652 xmlSchemaPCustomErr(ctxt,
14653 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14654 NULL, type, NULL,
14655 "If the content type is 'mixed', then the content type of the "
14656 "base type must also be 'mixed'", NULL);
14657 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14658 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014659 /*
14660 * SPEC (5.4.2) "The particle of the complex type definition itself
14661 * must be a ·valid restriction· of the particle of the {content
14662 * type} of the {base type definition} as defined in Particle Valid
14663 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014664 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014665 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014666 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014667 } else {
14668 xmlSchemaPCustomErr(ctxt,
14669 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14670 NULL, type, NULL,
14671 "The type is not a valid restriction of its base type", NULL);
14672 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14673 }
14674 return (0);
14675}
14676
14677/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014678 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014679 * @ctxt: the schema parser context
14680 * @type: the complex type definition
14681 *
14682 * (3.4.6) Constraints on Complex Type Definition Schema Components
14683 *
14684 * Returns 0 if the constraints are satisfied, a positive
14685 * error code if not and -1 if an internal error occured.
14686 */
14687static int
14688xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14689 xmlSchemaTypePtr type)
14690{
14691 int ret;
14692 /*
14693 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014694 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014695 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14696 if (ret != 0)
14697 return (ret);
14698 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14699 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14700 else
14701 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14702 return (ret);
14703}
14704
14705/**
14706 * xmlSchemaCheckSRCCT:
14707 * @ctxt: the schema parser context
14708 * @type: the complex type definition
14709 *
14710 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014711 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014712 * Complex Type Definition Representation OK (src-ct)
14713 *
14714 * Returns 0 if the constraints are satisfied, a positive
14715 * error code if not and -1 if an internal error occured.
14716 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014717static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014718xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014719 xmlSchemaTypePtr type)
14720{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014721 xmlSchemaTypePtr base;
14722 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014723
14724 /*
14725 * TODO: Adjust the error codes here, as I used
14726 * XML_SCHEMAP_SRC_CT_1 only yet.
14727 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014728 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014729 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014730 /*
14731 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014732 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014733 * must be a complex type definition;
14734 */
14735 if (! IS_COMPLEX_TYPE(base)) {
14736 xmlChar *str = NULL;
14737 xmlSchemaPCustomErr(ctxt,
14738 XML_SCHEMAP_SRC_CT_1,
14739 NULL, type, type->node,
14740 "If using <complexContent>, the base type is expected to be "
14741 "a complex type. The base type '%s' is a simple type",
14742 xmlSchemaFormatQName(&str, base->targetNamespace,
14743 base->name));
14744 FREE_AND_NULL(str)
14745 return (XML_SCHEMAP_SRC_CT_1);
14746 }
14747 } else {
14748 /*
14749 * SPEC
14750 * 2 If the <simpleContent> alternative is chosen, all of the
14751 * following must be true:
14752 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14753 * base [attribute] must be one of the following:
14754 */
14755 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014756 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014757 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14758 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014759 /*
14760 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014761 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014762 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014763 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014764 xmlSchemaPCustomErr(ctxt,
14765 XML_SCHEMAP_SRC_CT_1,
14766 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014767 "If using <simpleContent> and <restriction>, the base "
14768 "type must be a complex type. The base type '%s' is "
14769 "a simple type",
14770 xmlSchemaFormatQName(&str, base->targetNamespace,
14771 base->name));
14772 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014773 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014774 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014775 } else {
14776 /* Base type is a complex type. */
14777 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14778 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14779 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014780 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014781 * simple type definition;
14782 * PASS
14783 */
14784 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014785 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014786 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014787 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014788 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014789 type->name);
14790 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014791 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014792 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14793 (type->flags &
14794 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014795
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014796 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014797 * 2.1.2 only if the <restriction> alternative is also
14798 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014799 * is mixed and a particle emptiable.
14800 */
14801 if (! xmlSchemaIsParticleEmptiable(
14802 (xmlSchemaParticlePtr) base->subtypes)) {
14803 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014804 } else
14805 /*
14806 * Attention: at this point the <simpleType> child is in
14807 * ->contentTypeDef (put there during parsing).
14808 */
14809 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014810 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014811 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014812 * 2.2 If clause 2.1.2 above is satisfied, then there
14813 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014814 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014815 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014816 /* TODO: Change error code to ..._SRC_CT_2_2. */
14817 xmlSchemaPCustomErr(ctxt,
14818 XML_SCHEMAP_SRC_CT_1,
14819 NULL, type, NULL,
14820 "A <simpleType> is expected among the children "
14821 "of <restriction>, if <simpleContent> is used and "
14822 "the base type '%s' is a complex type",
14823 xmlSchemaFormatQName(&str, base->targetNamespace,
14824 base->name));
14825 FREE_AND_NULL(str)
14826 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014827 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014828 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014829 ret = XML_SCHEMAP_SRC_CT_1;
14830 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014831 }
14832 if (ret > 0) {
14833 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014834 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014835 xmlSchemaPCustomErr(ctxt,
14836 XML_SCHEMAP_SRC_CT_1,
14837 NULL, type, NULL,
14838 "If <simpleContent> and <restriction> is used, the "
14839 "base type must be a simple type or a complex type with "
14840 "mixed content and particle emptiable. The base type "
14841 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014842 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014843 base->name));
14844 } else {
14845 xmlSchemaPCustomErr(ctxt,
14846 XML_SCHEMAP_SRC_CT_1,
14847 NULL, type, NULL,
14848 "If <simpleContent> and <extension> is used, the "
14849 "base type must be a simple type. The base type '%s' "
14850 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014851 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014852 base->name));
14853 }
14854 FREE_AND_NULL(str)
14855 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014856 }
14857 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014858 * SPEC (3) "The corresponding complex type definition component must
14859 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014860 * Definition Schema Components (§3.4.6);"
14861 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014862 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014863 /*
14864 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014865 * above for {attribute wildcard} is satisfied, the intensional
14866 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014867 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014868 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014869 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014870 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014871}
William M. Brack2f2a6632004-08-20 23:09:47 +000014872
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014873#ifdef ENABLE_PARTICLE_RESTRICTION
14874/**
14875 * xmlSchemaCheckParticleRangeOK:
14876 * @ctxt: the schema parser context
14877 * @type: the complex type definition
14878 *
14879 * (3.9.6) Constraints on Particle Schema Components
14880 * Schema Component Constraint:
14881 * Occurrence Range OK (range-ok)
14882 *
14883 * STATUS: complete
14884 *
14885 * Returns 0 if the constraints are satisfied, a positive
14886 * error code if not and -1 if an internal error occured.
14887 */
14888static int
14889xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14890 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014891{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014892 if (rmin < bmin)
14893 return (1);
14894 if ((bmax != UNBOUNDED) &&
14895 (rmax > bmax))
14896 return (1);
14897 return (0);
14898}
14899
14900/**
14901 * xmlSchemaCheckRCaseNameAndTypeOK:
14902 * @ctxt: the schema parser context
14903 * @r: the restricting element declaration particle
14904 * @b: the base element declaration particle
14905 *
14906 * (3.9.6) Constraints on Particle Schema Components
14907 * Schema Component Constraint:
14908 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14909 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014910 *
14911 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014912 * MISSING (3.2.3)
14913 * CLARIFY: (3.2.2)
14914 *
14915 * Returns 0 if the constraints are satisfied, a positive
14916 * error code if not and -1 if an internal error occured.
14917 */
14918static int
14919xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14920 xmlSchemaParticlePtr r,
14921 xmlSchemaParticlePtr b)
14922{
14923 xmlSchemaElementPtr elemR, elemB;
14924
14925 /* TODO: Error codes (rcase-NameAndTypeOK). */
14926 elemR = (xmlSchemaElementPtr) r->children;
14927 elemB = (xmlSchemaElementPtr) b->children;
14928 /*
14929 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14930 * the same."
14931 */
14932 if ((elemR != elemB) &&
14933 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14934 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14935 return (1);
14936 /*
14937 * SPEC (2) "R's occurrence range is a valid restriction of B's
14938 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14939 */
14940 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14941 b->minOccurs, b->maxOccurs) != 0)
14942 return (1);
14943 /*
14944 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14945 * {scope} are global."
14946 */
14947 if (elemR == elemB)
14948 return (0);
14949 /*
14950 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14951 */
14952 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14953 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14954 return (1);
14955 /*
14956 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14957 * or is not fixed, or R's declaration's {value constraint} is fixed
14958 * with the same value."
14959 */
14960 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14961 ((elemR->value == NULL) ||
14962 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14963 /* TODO: Equality of the initial value or normalized or canonical? */
14964 (! xmlStrEqual(elemR->value, elemB->value))))
14965 return (1);
14966 /*
14967 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14968 * definitions} is a subset of B's declaration's {identity-constraint
14969 * definitions}, if any."
14970 */
14971 if (elemB->idcs != NULL) {
14972 /* TODO */
14973 }
14974 /*
14975 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14976 * superset of B's declaration's {disallowed substitutions}."
14977 */
14978 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14979 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14980 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14981 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14982 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14983 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14984 return (1);
14985 /*
14986 * SPEC (3.2.5) "R's {type definition} is validly derived given
14987 * {extension, list, union} from B's {type definition}"
14988 *
14989 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14990 * set, if the corresponding constraints handle "restriction" and
14991 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014992 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014993 */
14994 {
14995 int set = 0;
14996
14997 set |= SUBSET_EXTENSION;
14998 set |= SUBSET_LIST;
14999 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015000 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015001 elemB->subtypes, set) != 0)
15002 return (1);
15003 }
15004 return (0);
15005}
15006
15007/**
15008 * xmlSchemaCheckRCaseNSCompat:
15009 * @ctxt: the schema parser context
15010 * @r: the restricting element declaration particle
15011 * @b: the base wildcard particle
15012 *
15013 * (3.9.6) Constraints on Particle Schema Components
15014 * Schema Component Constraint:
15015 * Particle Derivation OK (Elt:Any -- NSCompat)
15016 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015017 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015018 * STATUS: complete
15019 *
15020 * Returns 0 if the constraints are satisfied, a positive
15021 * error code if not and -1 if an internal error occured.
15022 */
15023static int
15024xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
15025 xmlSchemaParticlePtr r,
15026 xmlSchemaParticlePtr b)
15027{
15028 /* TODO:Error codes (rcase-NSCompat). */
15029 /*
15030 * SPEC "For an element declaration particle to be a ·valid restriction·
15031 * of a wildcard particle all of the following must be true:"
15032 *
15033 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15034 * with respect to the wildcard's {namespace constraint} as defined by
15035 * Wildcard allows Namespace Name (§3.10.4)."
15036 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015037 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015038 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15039 return (1);
15040 /*
15041 * SPEC (2) "R's occurrence range is a valid restriction of B's
15042 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15043 */
15044 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15045 b->minOccurs, b->maxOccurs) != 0)
15046 return (1);
15047
15048 return (0);
15049}
15050
15051/**
15052 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15053 * @ctxt: the schema parser context
15054 * @r: the restricting element declaration particle
15055 * @b: the base model group particle
15056 *
15057 * (3.9.6) Constraints on Particle Schema Components
15058 * Schema Component Constraint:
15059 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15060 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015061 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015062 * STATUS: TODO
15063 *
15064 * Returns 0 if the constraints are satisfied, a positive
15065 * error code if not and -1 if an internal error occured.
15066 */
15067static int
15068xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15069 xmlSchemaParticlePtr r,
15070 xmlSchemaParticlePtr b)
15071{
15072 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15073 TODO
15074 return (0);
15075}
15076
15077/**
15078 * xmlSchemaCheckRCaseNSSubset:
15079 * @ctxt: the schema parser context
15080 * @r: the restricting wildcard particle
15081 * @b: the base wildcard particle
15082 *
15083 * (3.9.6) Constraints on Particle Schema Components
15084 * Schema Component Constraint:
15085 * Particle Derivation OK (Any:Any -- NSSubset)
15086 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015087 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015088 * STATUS: complete
15089 *
15090 * Returns 0 if the constraints are satisfied, a positive
15091 * error code if not and -1 if an internal error occured.
15092 */
15093static int
15094xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15095 xmlSchemaParticlePtr r,
15096 xmlSchemaParticlePtr b,
15097 int isAnyTypeBase)
15098{
15099 /* TODO: Error codes (rcase-NSSubset). */
15100 /*
15101 * SPEC (1) "R's occurrence range is a valid restriction of B's
15102 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15103 */
15104 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15105 b->minOccurs, b->maxOccurs))
15106 return (1);
15107 /*
15108 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15109 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15110 */
15111 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15112 (xmlSchemaWildcardPtr) b->children))
15113 return (1);
15114 /*
15115 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15116 * definition·, R's {process contents} must be identical to or stronger
15117 * than B's {process contents}, where strict is stronger than lax is
15118 * stronger than skip."
15119 */
15120 if (! isAnyTypeBase) {
15121 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15122 ((xmlSchemaWildcardPtr) b->children)->processContents)
15123 return (1);
15124 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015125
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015126 return (0);
15127}
15128
15129/**
15130 * xmlSchemaCheckCOSParticleRestrict:
15131 * @ctxt: the schema parser context
15132 * @type: the complex type definition
15133 *
15134 * (3.9.6) Constraints on Particle Schema Components
15135 * Schema Component Constraint:
15136 * Particle Valid (Restriction) (cos-particle-restrict)
15137 *
15138 * STATUS: TODO
15139 *
15140 * Returns 0 if the constraints are satisfied, a positive
15141 * error code if not and -1 if an internal error occured.
15142 */
15143static int
15144xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15145 xmlSchemaParticlePtr r,
15146 xmlSchemaParticlePtr b)
15147{
15148 int ret = 0;
15149
15150 /*part = GET_PARTICLE(type);
15151 basePart = GET_PARTICLE(base);
15152 */
15153
15154 TODO
15155
15156 /*
15157 * SPEC (1) "They are the same particle."
15158 */
15159 if (r == b)
15160 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015161
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015162
15163 return (0);
15164}
15165
15166/**
15167 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15168 * @ctxt: the schema parser context
15169 * @r: the model group particle
15170 * @b: the base wildcard particle
15171 *
15172 * (3.9.6) Constraints on Particle Schema Components
15173 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015174 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015175 * NSRecurseCheckCardinality)
15176 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015177 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015178 * STATUS: TODO: subst-groups
15179 *
15180 * Returns 0 if the constraints are satisfied, a positive
15181 * error code if not and -1 if an internal error occured.
15182 */
15183static int
15184xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15185 xmlSchemaParticlePtr r,
15186 xmlSchemaParticlePtr b)
15187{
15188 xmlSchemaParticlePtr part;
15189 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15190 if ((r->children == NULL) || (r->children->children == NULL))
15191 return (-1);
15192 /*
15193 * SPEC "For a group particle to be a ·valid restriction· of a
15194 * wildcard particle..."
15195 *
15196 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015197 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015198 * Particle Valid (Restriction) (§3.9.6)."
15199 */
15200 part = (xmlSchemaParticlePtr) r->children->children;
15201 do {
15202 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15203 return (1);
15204 part = (xmlSchemaParticlePtr) part->next;
15205 } while (part != NULL);
15206 /*
15207 * SPEC (2) "The effective total range of the group [...] is a
15208 * valid restriction of B's occurrence range as defined by
15209 * Occurrence Range OK (§3.9.6)."
15210 */
15211 if (xmlSchemaCheckParticleRangeOK(
15212 xmlSchemaGetParticleTotalRangeMin(r),
15213 xmlSchemaGetParticleTotalRangeMax(r),
15214 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015215 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015216 return (0);
15217}
15218
15219/**
15220 * xmlSchemaCheckRCaseRecurse:
15221 * @ctxt: the schema parser context
15222 * @r: the <all> or <sequence> model group particle
15223 * @b: the base <all> or <sequence> model group particle
15224 *
15225 * (3.9.6) Constraints on Particle Schema Components
15226 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015227 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015228 Recurse)
15229 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015230 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015231 * STATUS: ?
15232 * TODO: subst-groups
15233 *
15234 * Returns 0 if the constraints are satisfied, a positive
15235 * error code if not and -1 if an internal error occured.
15236 */
15237static int
15238xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15239 xmlSchemaParticlePtr r,
15240 xmlSchemaParticlePtr b)
15241{
15242 /* xmlSchemaParticlePtr part; */
15243 /* TODO: Error codes (rcase-Recurse). */
15244 if ((r->children == NULL) || (b->children == NULL) ||
15245 (r->children->type != b->children->type))
15246 return (-1);
15247 /*
15248 * SPEC "For an all or sequence group particle to be a ·valid
15249 * restriction· of another group particle with the same {compositor}..."
15250 *
15251 * SPEC (1) "R's occurrence range is a valid restriction of B's
15252 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15253 */
15254 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15255 b->minOccurs, b->maxOccurs))
15256 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015257
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015258
15259 return (0);
15260}
15261
15262#endif
15263
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015264#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15265 xmlSchemaPCustomErrExt(pctxt, \
15266 XML_SCHEMAP_INVALID_FACET_VALUE, \
15267 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15268 "It is an error for both '%s' and '%s' to be specified on the "\
15269 "same type definition", \
15270 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15271 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15272
15273#define FACET_RESTR_ERR(fac1, msg) \
15274 xmlSchemaPCustomErr(pctxt, \
15275 XML_SCHEMAP_INVALID_FACET_VALUE, \
15276 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015277 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015278
15279#define FACET_RESTR_FIXED_ERR(fac) \
15280 xmlSchemaPCustomErr(pctxt, \
15281 XML_SCHEMAP_INVALID_FACET_VALUE, \
15282 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15283 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015284 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015285
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015286static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015287xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15288 xmlSchemaFacetPtr facet1,
15289 xmlSchemaFacetPtr facet2,
15290 int lessGreater,
15291 int orEqual,
15292 int ofBase)
15293{
15294 xmlChar *msg = NULL;
15295
15296 msg = xmlStrdup(BAD_CAST "'");
15297 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15298 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15299 if (lessGreater == 0)
15300 msg = xmlStrcat(msg, BAD_CAST " equal to");
15301 if (lessGreater == 1)
15302 msg = xmlStrcat(msg, BAD_CAST " greater than");
15303 else
15304 msg = xmlStrcat(msg, BAD_CAST " less than");
15305
15306 if (orEqual)
15307 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15308 msg = xmlStrcat(msg, BAD_CAST " '");
15309 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15310 if (ofBase)
15311 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15312 else
15313 msg = xmlStrcat(msg, BAD_CAST "'");
15314
15315 xmlSchemaPCustomErr(pctxt,
15316 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015317 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015318 (const char *) msg, NULL);
15319
15320 if (msg != NULL)
15321 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015322}
15323
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015324static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015325xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15326 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015327{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015328 xmlSchemaTypePtr base = type->baseType;
15329 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015330 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015331 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15332 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15333 fmininc = NULL, fmaxinc = NULL,
15334 fminexc = NULL, fmaxexc = NULL,
15335 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15336 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15337 bfmininc = NULL, bfmaxinc = NULL,
15338 bfminexc = NULL, bfmaxexc = NULL;
15339 int res, err = 0, fixedErr;
15340 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015341 * 3 The {facets} of R are the union of S and the {facets}
15342 * of B, eliminating duplicates. To eliminate duplicates,
15343 * when a facet of the same kind occurs in both S and the
15344 * {facets} of B, the one in the {facets} of B is not
15345 * included, with the exception of enumeration and pattern
15346 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015347 * are allowed.
15348 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015349
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015350 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15351 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015352
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015353 last = type->facetSet;
15354 if (last != NULL)
15355 while (last->next != NULL)
15356 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015357
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015358 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15359 facet = cur->facet;
15360 switch (facet->type) {
15361 case XML_SCHEMA_FACET_LENGTH:
15362 flength = facet; break;
15363 case XML_SCHEMA_FACET_MINLENGTH:
15364 fminlen = facet; break;
15365 case XML_SCHEMA_FACET_MININCLUSIVE:
15366 fmininc = facet; break;
15367 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15368 fminexc = facet; break;
15369 case XML_SCHEMA_FACET_MAXLENGTH:
15370 fmaxlen = facet; break;
15371 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15372 fmaxinc = facet; break;
15373 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15374 fmaxexc = facet; break;
15375 case XML_SCHEMA_FACET_TOTALDIGITS:
15376 ftotdig = facet; break;
15377 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15378 ffracdig = facet; break;
15379 default:
15380 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015381 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015382 }
15383 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15384 facet = cur->facet;
15385 switch (facet->type) {
15386 case XML_SCHEMA_FACET_LENGTH:
15387 bflength = facet; break;
15388 case XML_SCHEMA_FACET_MINLENGTH:
15389 bfminlen = facet; break;
15390 case XML_SCHEMA_FACET_MININCLUSIVE:
15391 bfmininc = facet; break;
15392 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15393 bfminexc = facet; break;
15394 case XML_SCHEMA_FACET_MAXLENGTH:
15395 bfmaxlen = facet; break;
15396 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15397 bfmaxinc = facet; break;
15398 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15399 bfmaxexc = facet; break;
15400 case XML_SCHEMA_FACET_TOTALDIGITS:
15401 bftotdig = facet; break;
15402 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15403 bffracdig = facet; break;
15404 default:
15405 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015406 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015407 }
15408 err = 0;
15409 /*
15410 * length and minLength or maxLength (2.2) + (3.2)
15411 */
15412 if (flength && (fminlen || fmaxlen)) {
15413 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15414 "either of 'minLength' or 'maxLength' to be specified on "
15415 "the same type definition")
15416 }
15417 /*
15418 * Mutual exclusions in the same derivation step.
15419 */
15420 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015421 /*
15422 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015423 */
15424 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15425 }
15426 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015427 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015428 * SCC "minInclusive and minExclusive"
15429 */
15430 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015431 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015432
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015433 if (flength && bflength) {
15434 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015435 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015436 * The values have to be equal.
15437 */
15438 res = xmlSchemaCompareValues(flength->val, bflength->val);
15439 if (res == -2)
15440 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015441 if (res != 0)
15442 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15443 if ((res != 0) && (bflength->fixed)) {
15444 FACET_RESTR_FIXED_ERR(flength)
15445 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015446
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015447 }
15448 if (fminlen && bfminlen) {
15449 /*
15450 * SCC "minLength valid restriction"
15451 * minLength >= BASE minLength
15452 */
15453 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15454 if (res == -2)
15455 goto internal_error;
15456 if (res == -1)
15457 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15458 if ((res != 0) && (bfminlen->fixed)) {
15459 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015460 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015461 }
15462 if (fmaxlen && bfmaxlen) {
15463 /*
15464 * SCC "maxLength valid restriction"
15465 * maxLength <= BASE minLength
15466 */
15467 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15468 if (res == -2)
15469 goto internal_error;
15470 if (res == 1)
15471 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15472 if ((res != 0) && (bfmaxlen->fixed)) {
15473 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015474 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015475 }
15476 /*
15477 * SCC "length and minLength or maxLength"
15478 */
15479 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015480 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015481 if (flength) {
15482 if (! fminlen)
15483 flength = bflength;
15484 if (fminlen) {
15485 /* (1.1) length >= minLength */
15486 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15487 if (res == -2)
15488 goto internal_error;
15489 if (res == -1)
15490 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15491 }
15492 if (! fmaxlen)
15493 fmaxlen = bfmaxlen;
15494 if (fmaxlen) {
15495 /* (2.1) length <= maxLength */
15496 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15497 if (res == -2)
15498 goto internal_error;
15499 if (res == 1)
15500 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15501 }
15502 }
15503 if (fmaxinc) {
15504 /*
15505 * "maxInclusive"
15506 */
15507 if (fmininc) {
15508 /* SCC "maxInclusive >= minInclusive" */
15509 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15510 if (res == -2)
15511 goto internal_error;
15512 if (res == -1) {
15513 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15514 }
15515 }
15516 /*
15517 * SCC "maxInclusive valid restriction"
15518 */
15519 if (bfmaxinc) {
15520 /* maxInclusive <= BASE maxInclusive */
15521 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15522 if (res == -2)
15523 goto internal_error;
15524 if (res == 1)
15525 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15526 if ((res != 0) && (bfmaxinc->fixed)) {
15527 FACET_RESTR_FIXED_ERR(fmaxinc)
15528 }
15529 }
15530 if (bfmaxexc) {
15531 /* maxInclusive < BASE maxExclusive */
15532 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15533 if (res == -2)
15534 goto internal_error;
15535 if (res != -1) {
15536 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15537 }
15538 }
15539 if (bfmininc) {
15540 /* maxInclusive >= BASE minInclusive */
15541 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15542 if (res == -2)
15543 goto internal_error;
15544 if (res == -1) {
15545 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15546 }
15547 }
15548 if (bfminexc) {
15549 /* maxInclusive > BASE minExclusive */
15550 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15551 if (res == -2)
15552 goto internal_error;
15553 if (res != 1) {
15554 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15555 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015556 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015557 }
15558 if (fmaxexc) {
15559 /*
15560 * "maxExclusive >= minExclusive"
15561 */
15562 if (fminexc) {
15563 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15564 if (res == -2)
15565 goto internal_error;
15566 if (res == -1) {
15567 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15568 }
15569 }
15570 /*
15571 * "maxExclusive valid restriction"
15572 */
15573 if (bfmaxexc) {
15574 /* maxExclusive <= BASE maxExclusive */
15575 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15576 if (res == -2)
15577 goto internal_error;
15578 if (res == 1) {
15579 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15580 }
15581 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015582 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015583 }
15584 }
15585 if (bfmaxinc) {
15586 /* maxExclusive <= BASE maxInclusive */
15587 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15588 if (res == -2)
15589 goto internal_error;
15590 if (res == 1) {
15591 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15592 }
15593 }
15594 if (bfmininc) {
15595 /* maxExclusive > BASE minInclusive */
15596 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15597 if (res == -2)
15598 goto internal_error;
15599 if (res != 1) {
15600 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15601 }
15602 }
15603 if (bfminexc) {
15604 /* maxExclusive > BASE minExclusive */
15605 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15606 if (res == -2)
15607 goto internal_error;
15608 if (res != 1) {
15609 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15610 }
15611 }
15612 }
15613 if (fminexc) {
15614 /*
15615 * "minExclusive < maxInclusive"
15616 */
15617 if (fmaxinc) {
15618 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15619 if (res == -2)
15620 goto internal_error;
15621 if (res != -1) {
15622 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15623 }
15624 }
15625 /*
15626 * "minExclusive valid restriction"
15627 */
15628 if (bfminexc) {
15629 /* minExclusive >= BASE minExclusive */
15630 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15631 if (res == -2)
15632 goto internal_error;
15633 if (res == -1) {
15634 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15635 }
15636 if ((res != 0) && (bfminexc->fixed)) {
15637 FACET_RESTR_FIXED_ERR(fminexc)
15638 }
15639 }
15640 if (bfmaxinc) {
15641 /* minExclusive <= BASE maxInclusive */
15642 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15643 if (res == -2)
15644 goto internal_error;
15645 if (res == 1) {
15646 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15647 }
15648 }
15649 if (bfmininc) {
15650 /* minExclusive >= BASE minInclusive */
15651 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15652 if (res == -2)
15653 goto internal_error;
15654 if (res == -1) {
15655 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15656 }
15657 }
15658 if (bfmaxexc) {
15659 /* minExclusive < BASE maxExclusive */
15660 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15661 if (res == -2)
15662 goto internal_error;
15663 if (res != -1) {
15664 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15665 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015666 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015667 }
15668 if (fmininc) {
15669 /*
15670 * "minInclusive < maxExclusive"
15671 */
15672 if (fmaxexc) {
15673 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15674 if (res == -2)
15675 goto internal_error;
15676 if (res != -1) {
15677 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15678 }
15679 }
15680 /*
15681 * "minExclusive valid restriction"
15682 */
15683 if (bfmininc) {
15684 /* minInclusive >= BASE minInclusive */
15685 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15686 if (res == -2)
15687 goto internal_error;
15688 if (res == -1) {
15689 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15690 }
15691 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015692 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015693 }
15694 }
15695 if (bfmaxinc) {
15696 /* minInclusive <= BASE maxInclusive */
15697 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15698 if (res == -2)
15699 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000015700 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015701 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15702 }
15703 }
15704 if (bfminexc) {
15705 /* minInclusive > BASE minExclusive */
15706 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15707 if (res == -2)
15708 goto internal_error;
15709 if (res != 1)
15710 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15711 }
15712 if (bfmaxexc) {
15713 /* minInclusive < BASE maxExclusive */
15714 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15715 if (res == -2)
15716 goto internal_error;
15717 if (res != -1)
15718 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15719 }
15720 }
15721 if (ftotdig && bftotdig) {
15722 /*
15723 * SCC " totalDigits valid restriction"
15724 * totalDigits <= BASE totalDigits
15725 */
15726 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15727 if (res == -2)
15728 goto internal_error;
15729 if (res == 1)
15730 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15731 -1, 1, 1);
15732 if ((res != 0) && (bftotdig->fixed)) {
15733 FACET_RESTR_FIXED_ERR(ftotdig)
15734 }
15735 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015736 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015737 /*
15738 * SCC "fractionDigits valid restriction"
15739 * fractionDigits <= BASE fractionDigits
15740 */
15741 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15742 if (res == -2)
15743 goto internal_error;
15744 if (res == 1)
15745 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15746 -1, 1, 1);
15747 if ((res != 0) && (bffracdig->fixed)) {
15748 FACET_RESTR_FIXED_ERR(ffracdig)
15749 }
15750 }
15751 /*
15752 * SCC "fractionDigits less than or equal to totalDigits"
15753 */
15754 if (! ftotdig)
15755 ftotdig = bftotdig;
15756 if (! ffracdig)
15757 ffracdig = bffracdig;
15758 if (ftotdig && ffracdig) {
15759 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15760 if (res == -2)
15761 goto internal_error;
15762 if (res == 1)
15763 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15764 -1, 1, 0);
15765 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015766 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015767 * *Enumerations* won' be added here, since only the first set
15768 * of enumerations in the ancestor-or-self axis is used
15769 * for validation, plus we need to use the base type of those
15770 * enumerations for whitespace.
15771 *
15772 * *Patterns*: won't be add here, since they are ORed at
15773 * type level and ANDed at ancestor level. This will
15774 * happed during validation by walking the base axis
15775 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015776 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015777 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15778 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015779 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015780 * Special handling of enumerations and patterns.
15781 * TODO: hmm, they should not appear in the set, so remove this.
15782 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015783 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015784 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015785 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015786 /*
15787 * Search for a duplicate facet in the current type.
15788 */
15789 link = type->facetSet;
15790 err = 0;
15791 fixedErr = 0;
15792 while (link != NULL) {
15793 facet = link->facet;
15794 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015795 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015796 case XML_SCHEMA_FACET_WHITESPACE:
15797 /*
15798 * The whitespace must be stronger.
15799 */
15800 if (facet->whitespace < bfacet->whitespace) {
15801 FACET_RESTR_ERR(flength,
15802 "The 'whitespace' value has to be equal to "
15803 "or stronger than the 'whitespace' value of "
15804 "the base type")
15805 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015806 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015807 (facet->whitespace != bfacet->whitespace)) {
15808 FACET_RESTR_FIXED_ERR(facet)
15809 }
15810 break;
15811 default:
15812 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015813 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015814 /* Duplicate found. */
15815 break;
15816 }
15817 link = link->next;
15818 }
15819 /*
15820 * If no duplicate was found: add the base types's facet
15821 * to the set.
15822 */
15823 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015824 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015825 xmlMalloc(sizeof(xmlSchemaFacetLink));
15826 if (link == NULL) {
15827 xmlSchemaPErrMemory(pctxt,
15828 "deriving facets, creating a facet link", NULL);
15829 return (-1);
15830 }
15831 link->facet = cur->facet;
15832 link->next = NULL;
15833 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015834 type->facetSet = link;
15835 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015836 last->next = link;
15837 last = link;
15838 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015839
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015840 }
15841
15842 return (0);
15843internal_error:
15844 xmlSchemaPCustomErr(pctxt,
15845 XML_SCHEMAP_INVALID_FACET_VALUE,
15846 NULL, type, NULL,
15847 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15848 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015849}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015850
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015851static int
15852xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15853 xmlSchemaTypePtr type)
15854{
15855 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15856 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015857 * The actual value is then formed by replacing any union type
15858 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015859 * {member type definitions}, in order.
15860 */
15861 link = type->memberTypes;
15862 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015863
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015864 if (IS_NOT_TYPEFIXED(link->type))
15865 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15866
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015867 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015868 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015869 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015870 link->type = subLink->type;
15871 if (subLink->next != NULL) {
15872 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015873 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015874 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015875 while (subLink != NULL) {
15876 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015877 xmlMalloc(sizeof(xmlSchemaTypeLink));
15878 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015879 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015880 NULL);
15881 return (-1);
15882 }
15883 newLink->type = subLink->type;
15884 prevLink->next = newLink;
15885 prevLink = newLink;
15886 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015887
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015888 subLink = subLink->next;
15889 }
15890 }
15891 }
15892 }
15893 link = link->next;
15894 }
15895 return (0);
15896}
15897
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015898static void
15899xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15900{
15901 int has = 0, needVal = 0, normVal = 0;
15902
15903 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15904 if (has) {
15905 needVal = (type->baseType->flags &
15906 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15907 normVal = (type->baseType->flags &
15908 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15909 }
15910 if (type->facets != NULL) {
15911 xmlSchemaFacetPtr fac;
15912
15913 for (fac = type->facets; fac != NULL; fac = fac->next) {
15914 switch (fac->type) {
15915 case XML_SCHEMA_FACET_WHITESPACE:
15916 break;
15917 case XML_SCHEMA_FACET_PATTERN:
15918 normVal = 1;
15919 has = 1;
15920 break;
15921 case XML_SCHEMA_FACET_ENUMERATION:
15922 needVal = 1;
15923 normVal = 1;
15924 has = 1;
15925 break;
15926 default:
15927 has = 1;
15928 break;
15929 }
15930 }
15931 }
15932 if (normVal)
15933 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15934 if (needVal)
15935 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15936 if (has)
15937 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15938
15939 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15940 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15941 /*
15942 * OPTIMIZE VAL TODO: Some facets need a computed value.
15943 */
15944 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15945 (prim->builtInType != XML_SCHEMAS_STRING)) {
15946 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15947 }
15948 }
15949}
15950
15951static int
15952xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15953{
15954
15955
15956 /*
15957 * Evaluate the whitespace-facet value.
15958 */
15959 if (VARIETY_LIST(type)) {
15960 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15961 return (0);
15962 } else if (VARIETY_UNION(type))
15963 return (0);
15964
15965 if (type->facetSet != NULL) {
15966 xmlSchemaFacetLinkPtr lin;
15967
15968 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15969 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15970 switch (lin->facet->whitespace) {
15971 case XML_SCHEMAS_FACET_PRESERVE:
15972 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15973 break;
15974 case XML_SCHEMAS_FACET_REPLACE:
15975 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15976 break;
15977 case XML_SCHEMAS_FACET_COLLAPSE:
15978 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15979 break;
15980 default:
15981 return (-1);
15982 }
15983 return (0);
15984 }
15985 }
15986 }
15987 /*
15988 * For all ·atomic· datatypes other than string (and types ·derived·
15989 * by ·restriction· from it) the value of whiteSpace is fixed to
15990 * collapse
15991 */
15992 {
15993 xmlSchemaTypePtr anc;
15994
15995 for (anc = type->baseType; anc != NULL &&
15996 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15997 anc = anc->baseType) {
15998
15999 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
16000 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
16001 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
16002
16003 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
16004 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
16005 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
16006
16007 } else
16008 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16009 break;
16010 }
16011 }
16012 return (0);
16013 }
16014 return (0);
16015}
16016
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016017/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016018 * xmlSchemaTypeFixup:
16019 * @typeDecl: the schema type definition
16020 * @ctxt: the schema parser context
16021 *
16022 * Fixes the content model of the type.
16023 */
16024static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016025xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016026 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000016027{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016028 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000016029 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016030 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
16031 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016032 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016033 if (! IS_NOT_TYPEFIXED(type))
16034 return;
16035 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016036 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016037 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016038
16039 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016040 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016041 XML_SCHEMAP_INTERNAL,
16042 NULL, type, NULL,
16043 "Internal error: xmlSchemaTypeFixup, "
16044 "baseType is missing on '%s'", type->name);
16045 return;
16046 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016047
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016048 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016049 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016050
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016051 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016052 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016053 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016054 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016055 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016056 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16057 /*
16058 * Skip fixup if the base type is invalid.
16059 * TODO: Generate a warning!
16060 */
16061 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016062 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016063 /*
16064 * This basically checks if the base type can be derived.
16065 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016066 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016067 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16068 return;
16069 }
16070 /*
16071 * Fixup the content type.
16072 */
16073 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16074 /*
16075 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016076 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016077 if ((IS_COMPLEX_TYPE(baseType)) &&
16078 (baseType->contentTypeDef != NULL) &&
16079 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016080 xmlSchemaTypePtr contentBase, content;
16081 char buf[30];
16082 const xmlChar *tmpname;
16083 /*
16084 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016085 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016086 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016087 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016088 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016089 * SPEC (1.1) "the simple type definition corresponding to the
16090 * <simpleType> among the [children] of <restriction> if there
16091 * is one;"
16092 * Note that this "<simpleType> among the [children]" was put
16093 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016094 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016095 contentBase = type->contentTypeDef;
16096 type->contentTypeDef = NULL;
16097 } else {
16098 /*
16099 * (1.2) "...otherwise (<restriction> has no <simpleType>
16100 * among its [children]), the simple type definition which
16101 * is the {content type} of the ... base type."
16102 */
16103 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016104 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016105 /*
16106 * SPEC
16107 * "... a simple type definition which restricts the simple
16108 * type definition identified in clause 1.1 or clause 1.2
16109 * with a set of facet components"
16110 *
16111 * Create the anonymous simple type, which will be the content
16112 * type of the complex type.
16113 */
16114 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16115 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16116 content = xmlSchemaAddType(pctxt,
16117 pctxt->schema, tmpname, tmpname, type->node);
16118 if (content == NULL)
16119 return;
16120 /*
16121 * We will use the same node as for the <complexType>
16122 * to have it somehow anchored in the schema doc.
16123 */
16124 content->node = type->node;
16125 content->type = XML_SCHEMA_TYPE_SIMPLE;
16126 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16127 content->baseType = contentBase;
16128 /*
16129 * Move the facets, previously anchored on the complexType.
16130 */
16131 content->facets = type->facets;
16132 type->facets = NULL;
16133 content->facetSet = type->facetSet;
16134 type->facetSet = NULL;
16135
16136 type->contentTypeDef = content;
16137 if (IS_NOT_TYPEFIXED(contentBase))
16138 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16139 xmlSchemaTypeFixup(content, pctxt, NULL);
16140
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016141 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16142 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16143 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16144 /*
16145 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16146 * an emptiable particle, then a simple type definition which
16147 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016148 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016149 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016150 (type->contentTypeDef->baseType == NULL)) {
16151 /*
16152 * TODO: Check if this ever happens.
16153 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016154 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016155 XML_SCHEMAP_INTERNAL,
16156 NULL, type, NULL,
16157 "Internal error: xmlSchemaTypeFixup, "
16158 "complex type '%s': the <simpleContent><restriction> "
16159 "is missing a <simpleType> child, but was not catched "
16160 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016161 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016162 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16163 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16164 /*
16165 * SPEC (3) If <extension> + base is <complexType> with
16166 * <simpleType> content, "...then the {content type} of that
16167 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016168 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016169 if (baseType->contentTypeDef == NULL) {
16170 /*
16171 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16172 * should have catched this already.
16173 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016174 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016175 XML_SCHEMAP_INTERNAL,
16176 NULL, type, NULL,
16177 "Internal error: xmlSchemaTypeFixup, "
16178 "complex type '%s': the <extension>ed base type is "
16179 "a complex type with no simple content type",
16180 type->name);
16181 }
16182 type->contentTypeDef = baseType->contentTypeDef;
16183 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16184 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16185 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016186 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016187 * "... then that simple type definition"
16188 */
16189 type->contentTypeDef = baseType;
16190 } else {
16191 /*
16192 * TODO: Check if this ever happens.
16193 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016194 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016195 XML_SCHEMAP_INTERNAL,
16196 NULL, type, NULL,
16197 "Internal error: xmlSchemaTypeFixup, "
16198 "complex type '%s' with <simpleContent>: unhandled "
16199 "derivation case", type->name);
16200 }
16201 } else {
16202 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016203 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016204 (xmlSchemaParticlePtr) type->subtypes;
16205 /*
16206 * Corresponds to <complexType><complexContent>...
16207 *
16208 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016209 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016210 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016211 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016212 * Compute the "effective content":
16213 * (2.1.1) + (2.1.2) + (2.1.3)
16214 */
16215 if ((particle == NULL) ||
16216 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16217 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16218 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16219 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16220 (particle->minOccurs == 0))) &&
16221 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016222 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016223 /*
16224 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16225 * a particle whose properties are as follows:..."
16226 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016227 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016228 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16229 * NOTE that we sill assign it the <complexType> node to
16230 * somehow anchor it in the doc.
16231 */
16232 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016233 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016234 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016235 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016236 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016237 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016238 type->node, 1, 1);
16239 if (particle == NULL)
16240 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016241 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016242 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016243 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016244 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016245 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016246 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16247 if (particle->children == NULL)
16248 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016249
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016250 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016251 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016252 dummySequence = 1;
16253 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16254 } else {
16255 /*
16256 * SPEC (2.1.5) "otherwise empty"
16257 */
16258 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016259 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016260 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016261 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016262 * SPEC (2.2) "otherwise the particle corresponding to the
16263 * <all>, <choice>, <group> or <sequence> among the
16264 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016265 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016266 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16267 }
16268 /*
16269 * Compute the "content type".
16270 */
16271 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016272 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016273 * SPEC (3.1) "If <restriction>..."
16274 * (3.1.1) + (3.1.2) */
16275 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16276 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16277 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16278 }
16279 } else {
16280 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016281 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016282 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016283 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16284 /*
16285 * SPEC (3.2.1)
16286 */
16287 type->contentType = baseType->contentType;
16288 type->subtypes = baseType->subtypes;
16289 /*
16290 * NOTE that the effective mixed is ignored here.
16291 */
16292 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16293 /*
16294 * SPEC (3.2.2)
16295 */
16296 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16297 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16298 } else {
16299 /*
16300 * SPEC (3.2.3)
16301 */
16302 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16303 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16304 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016305 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016306 * {particles} are..."
16307 */
16308 if (! dummySequence) {
16309 xmlSchemaTreeItemPtr effectiveContent =
16310 (xmlSchemaTreeItemPtr) type->subtypes;
16311 /*
16312 * Create the particle.
16313 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016314 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016315 type->node, 1, 1);
16316 if (particle == NULL)
16317 return;
16318 /*
16319 * Create the "sequence" model group.
16320 */
16321 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016322 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016323 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16324 if (particle->children == NULL)
16325 return;
16326 type->subtypes = (xmlSchemaTypePtr) particle;
16327 /*
16328 * SPEC "the particle of the {content type} of
16329 * the ... base ..."
16330 * Create a duplicate of the base type's particle
16331 * and assign its "term" to it.
16332 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016333 particle->children->children =
16334 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16335 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016336 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016337 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016338 if (particle->children->children == NULL)
16339 return;
16340 particle = (xmlSchemaParticlePtr)
16341 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016342 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016343 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16344 /*
16345 * SPEC "followed by the ·effective content·."
16346 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016347 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016348 } else {
16349 /*
16350 * This is the case when there is already an empty
16351 * <sequence> with minOccurs==maxOccurs==1.
16352 * Just add the base types's content type.
16353 * NOTE that, although we miss to add an intermediate
16354 * <sequence>, this should produce no difference to
16355 * neither the regex compilation of the content model,
16356 * nor to the complex type contraints.
16357 */
16358 particle->children->children =
16359 (xmlSchemaTreeItemPtr) baseType->subtypes;
16360 }
16361 }
16362 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016363 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016364 /*
16365 * Apply the complex type component constraints; this will not
16366 * check attributes, since this is done in
16367 * xmlSchemaBuildAttributeValidation().
16368 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016369 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16370 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016371 /*
16372 * Inherit & check constraints for attributes.
16373 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016374 xmlSchemaBuildAttributeValidation(pctxt, type);
16375 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 /*
16377 * Simple Type Definition Schema Component
16378 */
16379 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016380 if (VARIETY_LIST(type)) {
16381 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016382 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016383 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016384 if (type->subtypes == NULL) {
16385 /*
16386 * This one is really needed, so get out.
16387 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016388 PERROR_INT("xmlSchemaTypeFixup",
16389 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016390 return;
16391 }
16392 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016393 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16394 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016395 /*
16396 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016397 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016398 if (type->memberTypes == NULL) {
16399 /*
16400 * This one is really needed, so get out.
16401 */
16402 return;
16403 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016404 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016405 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016406 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016407 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016408 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016409 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016410 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016411 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016412 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16413 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016414 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016415 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016416 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016417 */
16418 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016419 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016420 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016421 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16422 /*
16423 * Inherit the itemType.
16424 */
16425 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016426 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016427 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16428 /*
16429 * NOTE that we won't assign the memberTypes of the base,
16430 * since this will make trouble when freeing them; we will
16431 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016432 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016433 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016434 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016435 /*
16436 * Check constraints.
16437 *
16438 * TODO: Split this somehow, we need to know first if we can derive
16439 * from the base type at all!
16440 */
16441 if (type->baseType != NULL) {
16442 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016443 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016444 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016445 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016446 * applied beforehand.
16447 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016448 xmlSchemaCheckSRCSimpleType(pctxt, type);
16449 xmlSchemaCheckFacetValues(type, pctxt);
16450 if ((type->facetSet != NULL) ||
16451 (type->baseType->facetSet != NULL))
16452 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16453 /*
16454 * Whitespace value.
16455 */
16456 xmlSchemaTypeFixupWhitespace(type);
16457 xmlSchemaTypeFixupOptimFacets(type);
16458 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016459 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016460
Daniel Veillard8651f532002-04-17 09:06:27 +000016461#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016462 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016463 xmlGenericError(xmlGenericErrorContext,
16464 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016465 type->node->doc->URL,
16466 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016467 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016468 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016469 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016470 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16471 switch (type->contentType) {
16472 case XML_SCHEMA_CONTENT_SIMPLE:
16473 xmlGenericError(xmlGenericErrorContext, "simple\n");
16474 break;
16475 case XML_SCHEMA_CONTENT_ELEMENTS:
16476 xmlGenericError(xmlGenericErrorContext, "elements\n");
16477 break;
16478 case XML_SCHEMA_CONTENT_UNKNOWN:
16479 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16480 break;
16481 case XML_SCHEMA_CONTENT_EMPTY:
16482 xmlGenericError(xmlGenericErrorContext, "empty\n");
16483 break;
16484 case XML_SCHEMA_CONTENT_MIXED:
16485 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016486 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016487 xmlGenericError(xmlGenericErrorContext,
16488 "mixed as emptiable particle\n");
16489 else
16490 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16491 break;
16492 /* Removed, since not used. */
16493 /*
16494 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16495 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16496 break;
16497 */
16498 case XML_SCHEMA_CONTENT_BASIC:
16499 xmlGenericError(xmlGenericErrorContext, "basic\n");
16500 break;
16501 default:
16502 xmlGenericError(xmlGenericErrorContext,
16503 "not registered !!!\n");
16504 break;
16505 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016506 }
16507#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016508}
16509
16510/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016511 * xmlSchemaCheckFacet:
16512 * @facet: the facet
16513 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016514 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016515 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016516 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016517 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016518 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016519 * Returns 0 if valid, a positive error code if not valid and
16520 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016521 */
16522int
16523xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016524 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016525 xmlSchemaParserCtxtPtr pctxt,
16526 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016527{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016528 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016529
Daniel Veillardce682bc2004-11-05 17:22:25 +000016530 if ((facet == NULL) || (typeDecl == NULL))
16531 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016532 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016533 * TODO: will the parser context be given if used from
16534 * the relaxNG module?
16535 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016536 if (pctxt == NULL)
16537 ctxtGiven = 0;
16538 else
16539 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016540
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016541 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016542 case XML_SCHEMA_FACET_MININCLUSIVE:
16543 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16544 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016545 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16546 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016547 /*
16548 * Okay we need to validate the value
16549 * at that point.
16550 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016551 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016552
16553 /* 4.3.5.5 Constraints on enumeration Schema Components
16554 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016555 * It is an ·error· if any member of {value} is not in the
16556 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016557 *
16558 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016559 * The value ·must· be in the
16560 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016561 */
16562 /*
16563 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016564 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016565 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016566 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016567 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016568 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016569 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016570 */
16571 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16572 base = typeDecl->baseType;
16573 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016574 PERROR_INT("xmlSchemaCheckFacet",
16575 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016576 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016577 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016578 } else
16579 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016580
16581 if (! ctxtGiven) {
16582 /*
16583 * A context is needed if called from RelaxNG.
16584 */
16585 pctxt = xmlSchemaNewParserCtxt("*");
16586 if (pctxt == NULL)
16587 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016588 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016589 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016590 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016591 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016592 * facet->node is just the node holding the facet
16593 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016594 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016595 */
16596 ret = xmlSchemaVCheckCVCSimpleType(
16597 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16598 facet->value, &(facet->val), 1, 1, 0);
16599 if (ret != 0) {
16600 if (ret < 0) {
16601 /* No error message for RelaxNG. */
16602 if (ctxtGiven) {
16603 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16604 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16605 "Internal error: xmlSchemaCheckFacet, "
16606 "failed to validate the value '%s' of the "
16607 "facet '%s' against the base type",
16608 facet->value, xmlSchemaFacetTypeToString(facet->type));
16609 }
16610 goto internal_error;
16611 }
16612 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16613 /* No error message for RelaxNG. */
16614 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016615 xmlChar *str = NULL;
16616
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016617 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16618 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016619 "The value '%s' of the facet does not validate "
16620 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016621 facet->value,
16622 xmlSchemaFormatQName(&str,
16623 base->targetNamespace, base->name));
16624 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016625 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016626 goto exit;
16627 } else if (facet->val == NULL) {
16628 if (ctxtGiven) {
16629 PERROR_INT("xmlSchemaCheckFacet",
16630 "value was not computed");
16631 }
16632 TODO
16633 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016634 break;
16635 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016636 case XML_SCHEMA_FACET_PATTERN:
16637 facet->regexp = xmlRegexpCompile(facet->value);
16638 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016639 ret = XML_SCHEMAP_REGEXP_INVALID;
16640 /* No error message for RelaxNG. */
16641 if (ctxtGiven) {
16642 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16643 ret, facet->node, typeDecl,
16644 "The value '%s' of the facet 'pattern' is not a "
16645 "valid regular expression",
16646 facet->value, NULL);
16647 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016648 }
16649 break;
16650 case XML_SCHEMA_FACET_TOTALDIGITS:
16651 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16652 case XML_SCHEMA_FACET_LENGTH:
16653 case XML_SCHEMA_FACET_MAXLENGTH:
16654 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016655 ret = xmlSchemaValidatePredefinedType(
16656 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16657 facet->value, &(facet->val));
16658 if (ret != 0) {
16659 if (ret < 0) {
16660 /* No error message for RelaxNG. */
16661 if (ctxtGiven) {
16662 PERROR_INT("xmlSchemaCheckFacet",
16663 "validating facet value");
16664 }
16665 goto internal_error;
16666 }
16667 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16668 /* No error message for RelaxNG. */
16669 if (ctxtGiven) {
16670 /* error code */
16671 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16672 ret, facet->node, typeDecl,
16673 "The value '%s' of the facet '%s' is not a valid "
16674 "'nonNegativeInteger'",
16675 facet->value,
16676 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016677 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016678 }
16679 break;
16680 }
16681 case XML_SCHEMA_FACET_WHITESPACE:{
16682 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16683 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16684 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16685 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16686 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16687 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16688 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016689 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16690 /* No error message for RelaxNG. */
16691 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016692 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016693 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16694 ret, facet->node, typeDecl,
16695 "The value '%s' of the facet 'whitespace' is not "
16696 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016697 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016698 }
16699 }
16700 default:
16701 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016702 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016703exit:
16704 if ((! ctxtGiven) && (pctxt != NULL))
16705 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016706 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016707internal_error:
16708 if ((! ctxtGiven) && (pctxt != NULL))
16709 xmlSchemaFreeParserCtxt(pctxt);
16710 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016711}
16712
16713/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016714 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016715 * @typeDecl: the schema type definition
16716 * @ctxt: the schema parser context
16717 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016718 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016719 */
16720static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016721xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16722 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016723{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016724 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016725 /*
16726 * NOTE: It is intended to use the facets list, instead
16727 * of facetSet.
16728 */
16729 if (typeDecl->facets != NULL) {
16730 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016731
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016732 /*
16733 * Temporarily assign the "schema" to the validation context
16734 * of the parser context. This is needed for NOTATION validation.
16735 */
16736 if (ctxt->vctxt == NULL) {
16737 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16738 return;
16739 }
16740 ctxt->vctxt->schema = ctxt->schema;
16741
Daniel Veillard01fa6152004-06-29 17:04:39 +000016742 while (facet != NULL) {
16743 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16744 facet = facet->next;
16745 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016746
16747 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016748 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016749}
16750
16751/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016752 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016753 * @ctxtMGroup: the searched model group
16754 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016755 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016756 *
16757 * This one is intended to be used by
16758 * xmlSchemaCheckGroupDefCircular only.
16759 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016760 * Returns the particle with the circular model group definition reference,
16761 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016762 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016763static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016764xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016765 xmlSchemaTreeItemPtr particle)
16766{
16767 xmlSchemaTreeItemPtr circ = NULL;
16768 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016769 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016770
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016771 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016772 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016773 if (term == NULL)
16774 continue;
16775 switch (term->type) {
16776 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016777 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016778 if (gdef == groupDef)
16779 return (particle);
16780 /*
16781 * Mark this model group definition to avoid infinite
16782 * recursion on circular references not yet examined.
16783 */
16784 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16785 continue;
16786 if (gdef->children != NULL) {
16787 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16788 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16789 gdef->children->children);
16790 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16791 if (circ != NULL)
16792 return (circ);
16793 }
16794 break;
16795 case XML_SCHEMA_TYPE_SEQUENCE:
16796 case XML_SCHEMA_TYPE_CHOICE:
16797 case XML_SCHEMA_TYPE_ALL:
16798 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16799 if (circ != NULL)
16800 return (circ);
16801 break;
16802 default:
16803 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016804 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016805 }
16806 return (NULL);
16807}
16808
16809/**
16810 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016811 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016812 * @ctxt: the parser context
16813 * @name: the name
16814 *
16815 * Checks for circular references to model group definitions.
16816 */
16817static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016818xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016819 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016820 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016821{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016822 /*
16823 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016824 * 2 Circular groups are disallowed. That is, within the {particles}
16825 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016826 * is the group itself.
16827 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016828 if ((item == NULL) ||
16829 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16830 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016831 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016832 {
16833 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016834
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016835 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016836 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016837 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016838 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016839 * TODO: The error report is not adequate: this constraint
16840 * is defined for model groups but not definitions, but since
16841 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016842 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016843 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016844 */
16845 xmlSchemaPCustomErr(ctxt,
16846 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016847 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016848 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016849 "defined", xmlSchemaFormatQName(&str,
16850 item->targetNamespace, item->name));
16851 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016852 /*
16853 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016854 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016855 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016856 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016857 }
16858 }
16859}
16860
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016861/**
16862 * xmlSchemaGroupDefTermFixup:
16863 * @item: the particle with a model group definition as term
16864 * @ctxt: the parser context
16865 * @name: the name
16866 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016867 * Checks cos-all-limited.
16868 *
16869 * Assigns the model group of model group definitions to the "term"
16870 * of the referencing particle.
16871 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16872 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016873 */
16874static void
16875xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016876 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016877 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016878{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016879 if ((item == NULL) ||
16880 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16881 (item->children == NULL) ||
16882 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16883 (item->children->children == NULL))
16884 return;
16885 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016886 /*
16887 * TODO: Not nice, but we will anchor cos-all-limited here.
16888 */
16889 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16890 (item->maxOccurs != 1)) {
16891 /*
16892 * SPEC (1.2) "the {term} property of a particle with
16893 * {max occurs}=1which is part of a pair which constitutes the
16894 * {content type} of a complex type definition."
16895 */
16896 xmlSchemaPCustomErr(ctxt,
16897 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16898 NULL, (xmlSchemaTypePtr) item, item->node,
16899 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16900 "group is its term", NULL);
16901 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016902}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016903
16904/**
16905 * xmlSchemaGetCircAttrGrRef:
16906 * @ctxtGr: the searched attribute group
16907 * @attr: the current attribute list to be processed
16908 *
16909 * This one is intended to be used by
16910 * xmlSchemaCheckSRCAttributeGroupCircular only.
16911 *
16912 * Returns the circular attribute grou reference, otherwise NULL.
16913 */
16914static xmlSchemaAttributeGroupPtr
16915xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16916 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016917{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016918 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16919 int marked;
16920 /*
16921 * We will search for an attribute group reference which
16922 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016923 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016924 while (attr != NULL) {
16925 marked = 0;
16926 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16927 gr = (xmlSchemaAttributeGroupPtr) attr;
16928 if (gr->refItem != NULL) {
16929 if (gr->refItem == ctxtGr)
16930 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016931 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016932 XML_SCHEMAS_ATTRGROUP_MARKED) {
16933 attr = attr->next;
16934 continue;
16935 } else {
16936 /*
16937 * Mark as visited to avoid infinite recursion on
16938 * circular references not yet examined.
16939 */
16940 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16941 marked = 1;
16942 }
16943 }
16944 if (gr->attributes != NULL)
16945 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16946 /*
16947 * Unmark the visited group's attributes.
16948 */
16949 if (marked)
16950 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16951 if (circ != NULL)
16952 return (circ);
16953 }
16954 attr = attr->next;
16955 }
16956 return (NULL);
16957}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016958
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016959/**
16960 * xmlSchemaCheckSRCAttributeGroupCircular:
16961 * attrGr: the attribute group definition
16962 * @ctxt: the parser context
16963 * @name: the name
16964 *
16965 * Checks for circular references of attribute groups.
16966 */
16967static void
16968xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016969 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016970 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016971{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016972 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016973 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016974 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016975 * 3 Circular group reference is disallowed outside <redefine>.
16976 * That is, unless this element information item's parent is
16977 * <redefine>, then among the [children], if any, there must
16978 * not be an <attributeGroup> with ref [attribute] which resolves
16979 * to the component corresponding to this <attributeGroup>. Indirect
16980 * circularity is also ruled out. That is, when QName resolution
16981 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16982 * any <attributeGroup>s with a ref [attribute] among the [children],
16983 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016984 * which resolves to the component corresponding to this <attributeGroup>.
16985 */
16986 /*
16987 * Only global components can be referenced.
16988 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016989 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016990 (attrGr->attributes == NULL))
16991 return;
16992 else {
16993 xmlSchemaAttributeGroupPtr circ;
16994
16995 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16996 if (circ != NULL) {
16997 /*
16998 * TODO: Report the referenced attr group as QName.
16999 */
17000 xmlSchemaPCustomErr(ctxt,
17001 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
17002 NULL, NULL, circ->node,
17003 "Circular reference to the attribute group '%s' "
17004 "defined", attrGr->name);
17005 /*
17006 * NOTE: We will cut the reference to avoid further
17007 * confusion of the processor.
17008 * BADSPEC: The spec should define how to process in this case.
17009 */
17010 circ->attributes = NULL;
17011 circ->refItem = NULL;
17012 }
17013 }
17014}
17015
17016/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000017017 * xmlSchemaAttrGrpFixup:
17018 * @attrgrpDecl: the schema attribute definition
17019 * @ctxt: the schema parser context
17020 * @name: the attribute name
17021 *
17022 * Fixes finish doing the computations on the attributes definitions
17023 */
17024static void
Daniel Veillard3646d642004-06-02 19:19:14 +000017025xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017026 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000017027{
17028 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000017029 name = attrgrp->name;
17030 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017031 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000017032 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017033 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017034
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017035 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017036 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017037 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017038 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017039 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017040 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17041 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017042 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017043 return;
17044 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017045 attrgrp->refItem = ref;
17046 /*
17047 * Check for self reference!
17048 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017049 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017050 attrgrp->attributes = ref->attributes;
17051 attrgrp->attributeWildcard = ref->attributeWildcard;
17052 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017053}
17054
17055/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017056 * xmlSchemaAttrCheckValConstr:
17057 * @item: an schema attribute declaration/use
17058 * @ctxt: a schema parser context
17059 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017060 *
17061 *
17062 * Schema Component Constraint: Attribute Declaration Properties Correct
17063 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017064 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017065 *
17066 * Fixes finish doing the computations on the attributes definitions
17067 */
17068static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017069xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017070 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017071 const xmlChar * name ATTRIBUTE_UNUSED)
17072{
17073
17074 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017075 * 2 if there is a {value constraint}, the canonical lexical
17076 * representation of its value must be ·valid· with respect
17077 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017078 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017079 if (item->defValue != NULL) {
17080 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017081
17082 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017083 PERROR_INT("xmlSchemaCheckAttrValConstr",
17084 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017085 return;
17086 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017087 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17088 item->node, item->subtypes, item->defValue, &(item->defVal),
17089 1, 1, 0);
17090 if (ret != 0) {
17091 if (ret < 0) {
17092 PERROR_INT("xmlSchemaAttrCheckValConstr",
17093 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017094 return;
17095 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017096 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17097 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17098 ret, item->node, (xmlSchemaTypePtr) item,
17099 "The value of the value constraint is not valid", NULL, NULL);
17100 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017101 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017102 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017103}
17104
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017105static xmlSchemaElementPtr
17106xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17107 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017108{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017109 xmlSchemaElementPtr ret;
17110
17111 if (SUBST_GROUP_AFF(ancestor) == NULL)
17112 return (NULL);
17113 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17114 return (ancestor);
17115
17116 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17117 return (NULL);
17118 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17119 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17120 SUBST_GROUP_AFF(ancestor));
17121 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17122
17123 return (ret);
17124}
17125
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017126/**
17127 * xmlSchemaCheckElemPropsCorrect:
17128 * @ctxt: a schema parser context
17129 * @decl: the element declaration
17130 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017131 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017132 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017133 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017134 *
17135 * STATUS:
17136 * missing: (6)
17137 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017138static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017139xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17140 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017141{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017142 int ret = 0;
17143 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017144 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017145 * SPEC (1) "The values of the properties of an element declaration
17146 * must be as described in the property tableau in The Element
17147 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17148 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017149 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017150 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017151 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017152
17153 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017154 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017155 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017156 * affiliation}, then {scope} must be global."
17157 */
17158 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17159 xmlSchemaPCustomErr(pctxt,
17160 XML_SCHEMAP_E_PROPS_CORRECT_3,
17161 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17162 "Only global element declarations can have a "
17163 "substitution group affiliation", NULL);
17164 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017165 }
17166 /*
17167 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17168 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017169 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017170 * property."
17171 */
17172 if (head == elemDecl)
17173 circ = head;
17174 else if (SUBST_GROUP_AFF(head) != NULL)
17175 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17176 else
17177 circ = NULL;
17178 if (circ != NULL) {
17179 xmlChar *strA = NULL, *strB = NULL;
17180
17181 xmlSchemaPCustomErrExt(pctxt,
17182 XML_SCHEMAP_E_PROPS_CORRECT_6,
17183 NULL, (xmlSchemaTypePtr) circ, circ->node,
17184 "The element declaration '%s' defines a circular "
17185 "substitution group to element declaration '%s'",
17186 xmlSchemaGetComponentQName(&strA, circ),
17187 xmlSchemaGetComponentQName(&strB, head),
17188 NULL);
17189 FREE_AND_NULL(strA)
17190 FREE_AND_NULL(strB)
17191 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17192 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017193 /*
17194 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017195 * the {type definition}
17196 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017197 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017198 * of the {substitution group exclusions} of the {substitution group
17199 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17200 * (if the {type definition} is complex) or as defined in
17201 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017202 * simple)."
17203 *
17204 * NOTE: {substitution group exclusions} means the values of the
17205 * attribute "final".
17206 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017207
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017208 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017209 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017210
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017211 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17212 set |= SUBSET_EXTENSION;
17213 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17214 set |= SUBSET_RESTRICTION;
17215
17216 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17217 ELEM_TYPE(head), set) != 0) {
17218 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17219
17220 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017221 xmlSchemaPCustomErrExt(pctxt,
17222 XML_SCHEMAP_E_PROPS_CORRECT_4,
17223 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017224 "The type definition '%s' was "
17225 "either rejected by the substitution group "
17226 "affiliation '%s', or not validly derived from its type "
17227 "definition '%s'",
17228 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017229 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017230 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017231 FREE_AND_NULL(strA)
17232 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017233 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017234 }
17235 }
17236 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017237 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017238 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017239 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017240 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017241 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017242 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017243 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017244 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017245 ((IS_SIMPLE_TYPE(typeDef) &&
17246 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017247 (IS_COMPLEX_TYPE(typeDef) &&
17248 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017249 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17250 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017251
17252 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17253 xmlSchemaPCustomErr(pctxt,
17254 XML_SCHEMAP_E_PROPS_CORRECT_5,
17255 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17256 "The type definition (or type definition's content type) is or "
17257 "is derived from ID; value constraints are not allowed in "
17258 "conjunction with such a type definition", NULL);
17259 } else if (elemDecl->value != NULL) {
17260 int vcret;
17261 xmlNodePtr node = NULL;
17262
17263 /*
17264 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17265 * representation of its value must be ·valid· with respect to the
17266 * {type definition} as defined in Element Default Valid (Immediate)
17267 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017268 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017269 if (typeDef == NULL) {
17270 xmlSchemaPErr(pctxt, elemDecl->node,
17271 XML_SCHEMAP_INTERNAL,
17272 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17273 "type is missing... skipping validation of "
17274 "the value constraint", NULL, NULL);
17275 return (-1);
17276 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017277 if (elemDecl->node != NULL) {
17278 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17279 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17280 BAD_CAST "fixed");
17281 else
17282 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17283 BAD_CAST "default");
17284 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017285 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17286 typeDef, elemDecl->value, &(elemDecl->defVal));
17287 if (vcret != 0) {
17288 if (vcret < 0) {
17289 PERROR_INT("xmlSchemaElemCheckValConstr",
17290 "failed to validate the value constraint of an "
17291 "element declaration");
17292 return (-1);
17293 }
17294 return (vcret);
17295 }
17296 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017297
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017298 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017299}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017300
17301/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017302 * xmlSchemaCheckElemSubstGroup:
17303 * @ctxt: a schema parser context
17304 * @decl: the element declaration
17305 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017306 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017307 * Schema Component Constraint:
17308 * Substitution Group (cos-equiv-class)
17309 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017310 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017311 * a list will be built for each subst. group head, holding all direct
17312 * referents to this head.
17313 * NOTE that this function needs:
17314 * 1. circular subst. groups to be checked beforehand
17315 * 2. the declaration's type to be derived from the head's type
17316 *
17317 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017318 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017319 */
17320static void
17321xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17322 xmlSchemaElementPtr elemDecl)
17323{
17324 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17325 /* SPEC (1) "Its {abstract} is false." */
17326 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17327 return;
17328 {
17329 xmlSchemaElementPtr head;
17330 xmlSchemaTypePtr headType, type;
17331 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017332 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017333 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17334 * {disallowed substitutions} as the blocking constraint, as defined in
17335 * Substitution Group OK (Transitive) (§3.3.6)."
17336 */
17337 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17338 head = SUBST_GROUP_AFF(head)) {
17339 set = 0;
17340 methSet = 0;
17341 /*
17342 * The blocking constraints.
17343 */
17344 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17345 continue;
17346 headType = head->subtypes;
17347 type = elemDecl->subtypes;
17348 if (headType == type)
17349 goto add_member;
17350 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17351 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17352 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17353 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17354 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017355 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017356 * "The set of all {derivation method}s involved in the
17357 * derivation of D's {type definition} from C's {type definition}
17358 * does not intersect with the union of the blocking constraint,
17359 * C's {prohibited substitutions} (if C is complex, otherwise the
17360 * empty set) and the {prohibited substitutions} (respectively the
17361 * empty set) of any intermediate {type definition}s in the
17362 * derivation of D's {type definition} from C's {type definition}."
17363 */
17364 /*
17365 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17366 * subst.head axis, the methSet does not need to be computed for
17367 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017368 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017369 /*
17370 * The set of all {derivation method}s involved in the derivation
17371 */
17372 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017373 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017374 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17375 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17376 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017377
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017378 if ((type->flags &
17379 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17380 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17381 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17382
17383 type = type->baseType;
17384 }
17385 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017386 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017387 * the head's type.
17388 */
17389 type = elemDecl->subtypes->baseType;
17390 while (type != NULL) {
17391 if (IS_COMPLEX_TYPE(type)) {
17392 if ((type->flags &
17393 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17394 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17395 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17396 if ((type->flags &
17397 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17398 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17399 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17400 } else
17401 break;
17402 if (type == headType)
17403 break;
17404 type = type->baseType;
17405 }
17406 if ((set != 0) &&
17407 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17408 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17409 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17410 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17411 continue;
17412 }
17413add_member:
17414 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17415 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17416 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17417 }
17418 }
17419}
17420
17421/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017422 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017423 * @item: an schema element declaration/particle
17424 * @ctxt: a schema parser context
17425 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017426 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017427 * Validates the value constraints of an element declaration.
17428 *
17429 * Fixes finish doing the computations on the element declarations.
17430 */
17431static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017432xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017433 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017434 const xmlChar * name ATTRIBUTE_UNUSED)
17435{
17436 if (elemDecl == NULL)
17437 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017438 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17439 return;
17440 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017441 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17442 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017443}
17444
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017445/**
17446 * xmlSchemaMiscRefFixup:
17447 * @item: an schema component
17448 * @ctxt: a schema parser context
17449 * @name: the internal name of the component
17450 *
17451 * Resolves references of misc. schema components.
17452 */
17453static void
17454xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017455 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017456 const xmlChar * name ATTRIBUTE_UNUSED)
17457{
17458 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017459 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017460 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17461 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17462 xmlSchemaTreeItemPtr refItem;
17463 /*
17464 * Resolve the reference.
17465 */
17466 item->children = NULL;
17467 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17468 ref->itemType, ref->name, ref->targetNamespace);
17469 if (refItem == NULL) {
17470 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017471 NULL, GET_NODE(item), "ref", ref->name,
17472 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017473 } else {
17474 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17475 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017476 * NOTE that we will assign the model group definition
17477 * itself to the "term" of the particle. This will ease
17478 * the check for circular model group definitions. After
17479 * that the "term" will be assigned the model group of the
17480 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017481 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017482 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017483 } else
17484 item->children = refItem;
17485 }
17486 }
17487 }
17488}
17489
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017490static int
17491xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17492 xmlSchemaValPtr y)
17493{
17494 xmlSchemaTypePtr tx, ty, ptx, pty;
17495 int ret;
17496
17497 while (x != NULL) {
17498 /* Same types. */
17499 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17500 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17501 ptx = xmlSchemaGetPrimitiveType(tx);
17502 pty = xmlSchemaGetPrimitiveType(ty);
17503 /*
17504 * (1) if a datatype T' is ·derived· by ·restriction· from an
17505 * atomic datatype T then the ·value space· of T' is a subset of
17506 * the ·value space· of T. */
17507 /*
17508 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17509 * from a common atomic ancestor T then the ·value space·s of T'
17510 * and T'' may overlap.
17511 */
17512 if (ptx != pty)
17513 return(0);
17514 /*
17515 * We assume computed values to be normalized, so do a fast
17516 * string comparison for string based types.
17517 */
17518 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17519 IS_ANY_SIMPLE_TYPE(ptx)) {
17520 if (! xmlStrEqual(
17521 xmlSchemaValueGetAsString(x),
17522 xmlSchemaValueGetAsString(y)))
17523 return (0);
17524 } else {
17525 ret = xmlSchemaCompareValuesWhtsp(
17526 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17527 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17528 if (ret == -2)
17529 return(-1);
17530 if (ret != 0)
17531 return(0);
17532 }
17533 /*
17534 * Lists.
17535 */
17536 x = xmlSchemaValueGetNext(x);
17537 if (x != NULL) {
17538 y = xmlSchemaValueGetNext(y);
17539 if (y == NULL)
17540 return (0);
17541 } else if (xmlSchemaValueGetNext(y) != NULL)
17542 return (0);
17543 else
17544 return (1);
17545 }
17546 return (0);
17547}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017548
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017549/**
17550 * xmlSchemaAttrFixup:
17551 * @item: an schema attribute declaration/use.
17552 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017553 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017554 *
17555 * Fixes finish doing the computations on attribute declarations/uses.
17556 */
17557static void
17558xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017559 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017560 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017561{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017562 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017563 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017564 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017565 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017566 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017567 * The simple type definition corresponding to the <simpleType> element
17568 * information item in the [children], if present, otherwise the simple
17569 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017570 * [attribute], if present, otherwise the ·simple ur-type definition·.
17571 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017572 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017573 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017574 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17575 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017576 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017577 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017578 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017579
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017580 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17581 item->typeNs);
17582 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017583 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017584 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017585 (xmlSchemaTypePtr) item, item->node,
17586 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017587 XML_SCHEMA_TYPE_SIMPLE, NULL);
17588 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017589 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017590
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017591 } else if (item->ref != NULL) {
17592 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017593
Daniel Veillardc0826a72004-08-10 14:17:33 +000017594 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017595 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017596 * attribute declaration.
17597 */
17598 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017599 * TODO: Evaluate, what errors could occur if the declaration is not
17600 * found. It might be possible that the "typefixup" might crash if
17601 * no ref declaration was found.
17602 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017603 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017604 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017605 xmlSchemaPResCompAttrErr(ctxt,
17606 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017607 (xmlSchemaTypePtr) item, item->node,
17608 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017609 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017610 return;
17611 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017612 item->refDecl = decl;
17613 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017614 item->subtypes = decl->subtypes;
17615 /*
17616 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017617 * au-props-correct.2: If the {attribute declaration} has a fixed
17618 * {value constraint}, then if the attribute use itself has a
17619 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017620 * that of the {attribute declaration}'s {value constraint}.
17621 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017622 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017623 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017624 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017625 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017626 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17627 NULL, NULL, item->node,
17628 "The attribute declaration has a 'fixed' value constraint "
17629 ", thus it must be 'fixed' in attribute use as well",
17630 NULL);
17631 } else {
17632 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17633 xmlSchemaPCustomErr(ctxt,
17634 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17635 NULL, NULL, item->node,
17636 "The 'fixed' value constraint of the attribute use "
17637 "must match the attribute declaration's value "
17638 "constraint '%s'",
17639 decl->defValue);
17640 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017641 }
17642 /*
17643 * FUTURE: One should change the values of the attr. use
17644 * if ever validation should be attempted even if the
17645 * schema itself was not fully valid.
17646 */
17647 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017648 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017649 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17650 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017651}
17652
17653/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017654 * xmlSchemaResolveIDCKeyRef:
17655 * @idc: the identity-constraint definition
17656 * @ctxt: the schema parser context
17657 * @name: the attribute name
17658 *
17659 * Resolve keyRef references to key/unique IDCs.
17660 */
17661static void
17662xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017663 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017664 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017665{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017666 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17667 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017668 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017669 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017670 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017671 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017672 idc->ref->targetNamespace);
17673 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017674 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017675 * TODO: It is actually not an error to fail to resolve.
17676 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017677 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017678 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017679 (xmlSchemaTypePtr) idc, idc->node,
17680 "refer", idc->ref->name,
17681 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017682 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17683 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017684 } else {
17685 if (idc->nbFields !=
17686 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17687 xmlChar *str = NULL;
17688 xmlSchemaIDCPtr refer;
17689
17690 refer = (xmlSchemaIDCPtr) idc->ref->item;
17691 /*
17692 * SPEC c-props-correct(2)
17693 * "If the {identity-constraint category} is keyref,
17694 * the cardinality of the {fields} must equal that of
17695 * the {fields} of the {referenced key}.
17696 */
17697 xmlSchemaPCustomErr(pctxt,
17698 XML_SCHEMAP_C_PROPS_CORRECT,
17699 NULL, (xmlSchemaTypePtr) idc, idc->node,
17700 "The cardinality of the keyref differs from the "
17701 "cardinality of the referenced key '%s'",
17702 xmlSchemaFormatQName(&str, refer->targetNamespace,
17703 refer->name)
17704 );
17705 FREE_AND_NULL(str)
17706 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017707 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017708 }
17709}
17710
17711/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017712 * xmlSchemaParse:
17713 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017714 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017715 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017716 * XML Shema struture which can be used to validate instances.
17717 * *WARNING* this interface is highly subject to change
17718 *
17719 * Returns the internal XML Schema structure built from the resource or
17720 * NULL in case of error
17721 */
17722xmlSchemaPtr
17723xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17724{
17725 xmlSchemaPtr ret = NULL;
17726 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017727 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017728 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017729
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017730 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017731 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017732 * the API; i.e. not automatically by the validated instance document.
17733 */
17734
Daniel Veillard4255d502002-04-16 15:50:10 +000017735 xmlSchemaInitTypes();
17736
Daniel Veillard6045c902002-10-09 21:13:59 +000017737 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017738 return (NULL);
17739
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017740 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017741 ctxt->counter = 0;
17742 ctxt->container = NULL;
17743
17744 /*
17745 * First step is to parse the input document into an DOM/Infoset
17746 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017747 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017748 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017749 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017750 if (doc == NULL) {
17751 xmlSchemaPErr(ctxt, NULL,
17752 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017753 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017754 ctxt->URL, NULL);
17755 return (NULL);
17756 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017757 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017758 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17759 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017760 if (doc == NULL) {
17761 xmlSchemaPErr(ctxt, NULL,
17762 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017763 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017764 NULL, NULL);
17765 return (NULL);
17766 }
17767 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017768 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017769 } else if (ctxt->doc != NULL) {
17770 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017771 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017772 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017773 xmlSchemaPErr(ctxt, NULL,
17774 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017775 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017776 NULL, NULL);
17777 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017778 }
17779
17780 /*
17781 * Then extract the root and Schema parse it
17782 */
17783 root = xmlDocGetRootElement(doc);
17784 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017785 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17786 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017787 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017788 if (!preserve) {
17789 xmlFreeDoc(doc);
17790 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017791 return (NULL);
17792 }
17793
17794 /*
17795 * Remove all the blank text nodes
17796 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017797 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017798
17799 /*
17800 * Then do the parsing for good
17801 */
17802 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017803 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017804 if (!preserve) {
17805 xmlFreeDoc(doc);
17806 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017807 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017808 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017809 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017810 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017811 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017812 ctxt->ctxtType = NULL;
17813 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017814
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017815 /*
17816 * Resolve base types of simple/complex types.
17817 */
17818 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017819
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017820 if (ctxt->nberrors != 0)
17821 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017822
17823 if (ret->volatiles != NULL) {
17824 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17825 int i;
17826 xmlSchemaTreeItemPtr item;
17827
17828 for (i = 0; i < list->nbItems; i++) {
17829 item = (xmlSchemaTreeItemPtr) list->items[i];
17830 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17831 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017832 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017833 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017834 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017835 * Then fixup all attributes declarations
17836 */
17837 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017838 /*
17839 * Then fixup all attributes group declarations
17840 */
17841 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17842 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017843 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017844 * Resolve identity-constraint keyRefs.
17845 */
17846 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017847 /*
17848 * Check type defnitions for circular references.
17849 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017850 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017851 xmlSchemaCheckTypeDefCircular, ctxt);
17852 /*
17853 * Check model groups defnitions for circular references.
17854 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017855 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017856 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017857 /*
17858 * Set the "term" of particles pointing to model group definitions
17859 * to the contained model group.
17860 */
17861 if (ret->volatiles != NULL) {
17862 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17863 int i;
17864 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017865
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017866 for (i = 0; i < list->nbItems; i++) {
17867 item = (xmlSchemaParticlePtr) list->items[i];
17868 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17869 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17870 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017871 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017872 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017873 * Check attribute groups for circular references.
17874 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017875 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17876 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017877 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017878 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017879 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017880 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017881 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017882 /*
17883 * We will stop here if the schema was not valid to avoid internal errors
17884 * on missing sub-components. This is not conforming to the spec, since it
17885 * allows missing components, but it might make further processing crash.
17886 * So see it as a very strict handling, which might be made more lax in the
17887 * future.
17888 */
17889 if (ctxt->nberrors != 0)
17890 goto exit;
17891 /*
17892 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017893 */
17894 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017895 /*
17896 * Validate the value constraint of attribute declarations/uses.
17897 */
17898 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017899 /*
17900 * Validate the value constraint of element declarations.
17901 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017902 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017903
17904 if (ctxt->nberrors != 0)
17905 goto exit;
17906
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017907 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017908 * TODO: cos-element-consistent, cos-all-limited
17909 *
17910 * Then build the content model for all complex types
17911 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017912 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017913 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017914
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017915exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017916 if (ctxt->nberrors != 0) {
17917 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017918 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017919 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017920 return (ret);
17921}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017922
Daniel Veillard4255d502002-04-16 15:50:10 +000017923/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017924 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017925 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017926 * @err: the error callback
17927 * @warn: the warning callback
17928 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017929 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017930 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017931 */
17932void
17933xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017934 xmlSchemaValidityErrorFunc err,
17935 xmlSchemaValidityWarningFunc warn, void *ctx)
17936{
Daniel Veillard4255d502002-04-16 15:50:10 +000017937 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017938 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017939 ctxt->error = err;
17940 ctxt->warning = warn;
17941 ctxt->userData = ctx;
17942}
17943
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017944/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017945 * xmlSchemaGetParserErrors:
17946 * @ctxt: a XMl-Schema parser context
17947 * @err: the error callback result
17948 * @warn: the warning callback result
17949 * @ctx: contextual data for the callbacks result
17950 *
17951 * Get the callback information used to handle errors for a parser context
17952 *
17953 * Returns -1 in case of failure, 0 otherwise
17954 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017955int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017956xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17957 xmlSchemaValidityErrorFunc * err,
17958 xmlSchemaValidityWarningFunc * warn, void **ctx)
17959{
17960 if (ctxt == NULL)
17961 return(-1);
17962 if (err != NULL)
17963 *err = ctxt->error;
17964 if (warn != NULL)
17965 *warn = ctxt->warning;
17966 if (ctx != NULL)
17967 *ctx = ctxt->userData;
17968 return(0);
17969}
17970
17971/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017972 * xmlSchemaFacetTypeToString:
17973 * @type: the facet type
17974 *
17975 * Convert the xmlSchemaTypeType to a char string.
17976 *
17977 * Returns the char string representation of the facet type if the
17978 * type is a facet and an "Internal Error" string otherwise.
17979 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017980static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017981xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17982{
17983 switch (type) {
17984 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017985 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017986 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017987 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017988 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017989 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017990 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017991 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017992 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017993 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017994 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017995 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017996 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017997 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017998 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017999 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018000 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018001 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018002 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018003 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018004 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018005 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018006 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018007 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018008 default:
18009 break;
18010 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018011 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018012}
18013
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018014static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000018015xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
18016{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018017 /*
18018 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000018019 * from xsd:string.
18020 */
18021 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018022 /*
18023 * Note that we assume a whitespace of preserve for anySimpleType.
18024 */
18025 if ((type->builtInType == XML_SCHEMAS_STRING) ||
18026 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
18027 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000018028 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018029 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018030 else {
18031 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018032 * For all ·atomic· datatypes other than string (and types ·derived·
18033 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000018034 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018035 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018036 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018037 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018038 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018039 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018040 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018041 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018042 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018043 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
18044 } else if (VARIETY_UNION(type)) {
18045 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
18046 } else if (VARIETY_ATOMIC(type)) {
18047 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
18048 return (XML_SCHEMA_WHITESPACE_PRESERVE);
18049 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
18050 return (XML_SCHEMA_WHITESPACE_REPLACE);
18051 else
18052 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018053 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018054 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018055}
18056
Daniel Veillard4255d502002-04-16 15:50:10 +000018057/************************************************************************
18058 * *
18059 * Simple type validation *
18060 * *
18061 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018062
Daniel Veillard4255d502002-04-16 15:50:10 +000018063
18064/************************************************************************
18065 * *
18066 * DOM Validation code *
18067 * *
18068 ************************************************************************/
18069
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018070static void
18071xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18072{
18073 int i, nbItems;
18074 xmlSchemaTypePtr item, *items;
18075
18076
18077 /*
18078 * During the Assemble of the schema ctxt->curItems has
18079 * been filled with the relevant new items. Fix those up.
18080 */
18081 nbItems = ctxt->assemble->nbItems;
18082 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018083
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018084 for (i = 0; i < nbItems; i++) {
18085 item = items[i];
18086 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018087 case XML_SCHEMA_TYPE_COMPLEX:
18088 case XML_SCHEMA_TYPE_SIMPLE:
18089 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18090 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018091 case XML_SCHEMA_TYPE_ATTRIBUTE:
18092 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18093 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018094 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018095 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018096 ctxt, NULL);
18097 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018098 case XML_SCHEMA_TYPE_PARTICLE:
18099 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018100 break;
18101 case XML_SCHEMA_TYPE_IDC_KEY:
18102 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18103 case XML_SCHEMA_TYPE_IDC_KEYREF:
18104 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18105 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018106 default:
18107 break;
18108 }
18109 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018110 if (ctxt->nberrors != 0)
18111 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018112 /*
18113 * Circularity checks.
18114 */
18115 for (i = 0; i < nbItems; i++) {
18116 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018117 switch (item->type) {
18118 case XML_SCHEMA_TYPE_COMPLEX:
18119 case XML_SCHEMA_TYPE_SIMPLE:
18120 xmlSchemaCheckTypeDefCircular(
18121 (xmlSchemaTypePtr) item, ctxt, NULL);
18122 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018123 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018124 xmlSchemaCheckGroupDefCircular(
18125 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018126 break;
18127 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18128 xmlSchemaCheckAttributeGroupCircular(
18129 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18130 break;
18131 default:
18132 break;
18133 }
18134 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018135 if (ctxt->nberrors != 0)
18136 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018137 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018138 * Set the "term" of particles pointing to model group definitions
18139 * to the contained model group.
18140 */
18141 for (i = 0; i < nbItems; i++) {
18142 item = items[i];
18143 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18144 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018145 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018146 XML_SCHEMA_TYPE_GROUP)) {
18147 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18148 ctxt, NULL);
18149 }
18150 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018151 if (ctxt->nberrors != 0)
18152 return;
18153 for (i = 0; i < nbItems; i++) {
18154 item = items[i];
18155 switch (item->type) {
18156 case XML_SCHEMA_TYPE_ELEMENT:
18157 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18158 NULL, NULL, NULL);
18159 break;
18160 default:
18161 break;
18162 }
18163 }
18164 if (ctxt->nberrors != 0)
18165 return;
18166
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018167 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018168 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018169 */
18170 for (i = 0; i < nbItems; i++) {
18171 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018172 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018173 case XML_SCHEMA_TYPE_SIMPLE:
18174 case XML_SCHEMA_TYPE_COMPLEX:
18175 xmlSchemaTypeFixup(item, ctxt, NULL);
18176 break;
18177 default:
18178 break;
18179 }
18180 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018181 if (ctxt->nberrors != 0)
18182 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018183 /*
18184 * Validate value contraint values.
18185 */
18186 for (i = 0; i < nbItems; i++) {
18187 item = items[i];
18188 switch (item->type) {
18189 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018190 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18191 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018192 break;
18193 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018194 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018195 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018196 break;
18197 default:
18198 break;
18199 }
18200 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018201 if (ctxt->nberrors != 0)
18202 return;
18203 /*
18204 * Build the content model for complex types.
18205 */
18206 for (i = 0; i < nbItems; i++) {
18207 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018208 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018209 case XML_SCHEMA_TYPE_COMPLEX:
18210 xmlSchemaBuildContentModel(item, ctxt, NULL);
18211 break;
18212 default:
18213 break;
18214 }
18215 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018216}
18217
18218/**
18219 * xmlSchemaAssembleByLocation:
18220 * @pctxt: a schema parser context
18221 * @vctxt: a schema validation context
18222 * @schema: the existing schema
18223 * @node: the node that fired the assembling
18224 * @nsName: the namespace name of the new schema
18225 * @location: the location of the schema
18226 *
18227 * Expands an existing schema by an additional schema.
18228 *
18229 * Returns 0 if the new schema is correct, a positive error code
18230 * number otherwise and -1 in case of an internal or API error.
18231 */
18232static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018233xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018234 xmlSchemaPtr schema,
18235 xmlNodePtr node,
18236 const xmlChar *nsName,
18237 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018238{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018239 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018240 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018241 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018242 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018243 xmlSchemaParserCtxtPtr pctxt;
18244
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018245 /*
18246 * This should be used:
18247 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018248 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018249 * 3. if requested via the API
18250 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018251 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018252 return (-1);
18253 /*
18254 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018255 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018256 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018257 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18258 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018259 pctxt = vctxt->pctxt;
18260 /*
18261 * Set the counter to produce unique names for anonymous items.
18262 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018263 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018264 /*
18265 * Acquire the schema document.
18266 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018267 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18268 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018269 if (ret != 0) {
18270 if (doc != NULL)
18271 xmlFreeDoc(doc);
18272 } else if (doc != NULL) {
18273 docElem = xmlDocGetRootElement(doc);
18274 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018275 * Create new assemble info.
18276 */
18277 if (pctxt->assemble == NULL) {
18278 pctxt->assemble = xmlSchemaNewAssemble();
18279 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018280 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018281 "Memory error: xmlSchemaAssembleByLocation, "
18282 "allocating assemble info", NULL);
18283 xmlFreeDoc(doc);
18284 return (-1);
18285 }
18286 }
18287 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018288 * Save and reset the context & schema.
18289 */
18290 oldflags = schema->flags;
18291 oldtns = schema->targetNamespace;
18292 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018293 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018294
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018295 xmlSchemaClearSchemaDefaults(schema);
18296 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018297 if ((targetNs != NULL) &&
18298 xmlStrEqual(targetNs, xmlSchemaNs)) {
18299 /*
18300 * We are parsing the schema for schema!
18301 */
18302 vctxt->pctxt->isS4S = 1;
18303 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018304 /* schema->nbCurItems = 0; */
18305 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018306 pctxt->ctxtType = NULL;
18307 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018308
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018309 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18310 if (pctxt->nberrors != 0) {
18311 vctxt->nberrors += pctxt->nberrors;
18312 goto finally;
18313 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018314 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018315 if (pctxt->nberrors != 0) {
18316 vctxt->nberrors += pctxt->nberrors;
18317 goto finally;
18318 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018319 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018320 if (pctxt->nberrors != 0)
18321 vctxt->nberrors += pctxt->nberrors;
18322finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018323 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018324 * Set the counter of items.
18325 */
18326 schema->counter = pctxt->counter;
18327 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018328 * Free the list of assembled components.
18329 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018330 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018331 /*
18332 * Restore the context & schema.
18333 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018334 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018335 schema->flags = oldflags;
18336 schema->targetNamespace = oldtns;
18337 schema->doc = olddoc;
18338 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018339 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018340 return (ret);
18341}
18342
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018343static xmlSchemaAttrInfoPtr
18344xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18345 int metaType)
18346{
18347 if (vctxt->nbAttrInfos == 0)
18348 return (NULL);
18349 {
18350 int i;
18351 xmlSchemaAttrInfoPtr iattr;
18352
18353 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18354 iattr = vctxt->attrInfos[i];
18355 if (iattr->metaType == metaType)
18356 return (iattr);
18357 }
18358
18359 }
18360 return (NULL);
18361}
18362
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018363/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018364 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018365 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018366 *
18367 * Expands an existing schema by an additional schema using
18368 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18369 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18370 * must be set to 1.
18371 *
18372 * Returns 0 if the new schema is correct, a positive error code
18373 * number otherwise and -1 in case of an internal or API error.
18374 */
18375static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018376xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018377{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018378 const xmlChar *cur, *end;
18379 const xmlChar *nsname = NULL, *location;
18380 int count = 0;
18381 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018382 xmlSchemaAttrInfoPtr iattr;
18383
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018384 /*
18385 * Parse the value; we will assume an even number of values
18386 * to be given (this is how Xerces and XSV work).
18387 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018388 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18389 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18390 if (iattr == NULL)
18391 xmlSchemaGetMetaAttrInfo(vctxt,
18392 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18393 if (iattr == NULL)
18394 return (0);
18395 cur = iattr->value;
18396 do {
18397 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018398 /*
18399 * Get the namespace name.
18400 */
18401 while (IS_BLANK_CH(*cur))
18402 cur++;
18403 end = cur;
18404 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18405 end++;
18406 if (end == cur)
18407 break;
18408 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018409 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018410 cur = end;
18411 }
18412 /*
18413 * Get the URI.
18414 */
18415 while (IS_BLANK_CH(*cur))
18416 cur++;
18417 end = cur;
18418 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18419 end++;
18420 if (end == cur)
18421 break;
18422 count++;
18423 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018424 cur = end;
18425 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18426 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018427 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018428 VERROR_INT("xmlSchemaAssembleByXSI",
18429 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018430 return (-1);
18431 }
18432 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018433 return (ret);
18434}
18435
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018436#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018437
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018438static const xmlChar *
18439xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18440 const xmlChar *prefix)
18441{
18442 if (vctxt->sax != NULL) {
18443 int i, j;
18444 xmlSchemaNodeInfoPtr inode;
18445
18446 for (i = vctxt->depth; i >= 0; i--) {
18447 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18448 inode = vctxt->elemInfos[i];
18449 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18450 if (((prefix == NULL) &&
18451 (inode->nsBindings[j] == NULL)) ||
18452 ((prefix != NULL) && xmlStrEqual(prefix,
18453 inode->nsBindings[j]))) {
18454
18455 /*
18456 * Note that the namespace bindings are already
18457 * in a string dict.
18458 */
18459 return (inode->nsBindings[j+1]);
18460 }
18461 }
18462 }
18463 }
18464 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018465#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018466 } else if (vctxt->reader != NULL) {
18467 xmlChar *nsName;
18468
18469 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18470 if (nsName != NULL) {
18471 const xmlChar *ret;
18472
18473 VAL_CREATE_DICT;
18474 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18475 xmlFree(nsName);
18476 return (ret);
18477 } else
18478 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018479#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018480 } else {
18481 xmlNsPtr ns;
18482
18483 if ((vctxt->inode->node == NULL) ||
18484 (vctxt->inode->node->doc == NULL)) {
18485 VERROR_INT("xmlSchemaLookupNamespace",
18486 "no node or node's doc avaliable");
18487 return (NULL);
18488 }
18489 ns = xmlSearchNs(vctxt->inode->node->doc,
18490 vctxt->inode->node, prefix);
18491 if (ns != NULL)
18492 return (ns->href);
18493 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018494 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018495}
18496
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018497/*
18498* This one works on the schema of the validation context.
18499*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018500static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018501xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18502 xmlSchemaPtr schema,
18503 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018504 const xmlChar *value,
18505 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018506 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018507{
18508 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018509
18510 if (vctxt && (vctxt->schema == NULL)) {
18511 VERROR_INT("xmlSchemaValidateNotation",
18512 "a schema is needed on the validation context");
18513 return (-1);
18514 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018515 ret = xmlValidateQName(value, 1);
18516 if (ret != 0)
18517 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018518 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018519 xmlChar *localName = NULL;
18520 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018521
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018522 localName = xmlSplitQName2(value, &prefix);
18523 if (prefix != NULL) {
18524 const xmlChar *nsName = NULL;
18525
18526 if (vctxt != NULL)
18527 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18528 else if (node != NULL) {
18529 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18530 if (ns != NULL)
18531 nsName = ns->href;
18532 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018533 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018534 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018535 return (1);
18536 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018537 if (nsName == NULL) {
18538 xmlFree(prefix);
18539 xmlFree(localName);
18540 return (1);
18541 }
18542 if (xmlHashLookup2(schema->notaDecl, localName,
18543 nsName) != NULL) {
18544 if (valNeeded && (val != NULL)) {
18545 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18546 BAD_CAST xmlStrdup(nsName));
18547 if (*val == NULL)
18548 ret = -1;
18549 }
18550 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018551 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018552 xmlFree(prefix);
18553 xmlFree(localName);
18554 } else {
18555 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18556 if (valNeeded && (val != NULL)) {
18557 (*val) = xmlSchemaNewNOTATIONValue(
18558 BAD_CAST xmlStrdup(value), NULL);
18559 if (*val == NULL)
18560 ret = -1;
18561 }
18562 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018563 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018564 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018565 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018566 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018567}
18568
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018569/************************************************************************
18570 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018571 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018572 * *
18573 ************************************************************************/
18574
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018575/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018576 * xmlSchemaAugmentIDC:
18577 * @idcDef: the IDC definition
18578 *
18579 * Creates an augmented IDC definition item.
18580 *
18581 * Returns the item, or NULL on internal errors.
18582 */
18583static void
18584xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18585 xmlSchemaValidCtxtPtr vctxt)
18586{
18587 xmlSchemaIDCAugPtr aidc;
18588
18589 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18590 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018591 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018592 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18593 NULL);
18594 return;
18595 }
18596 aidc->bubbleDepth = -1;
18597 aidc->def = idcDef;
18598 aidc->next = NULL;
18599 if (vctxt->aidcs == NULL)
18600 vctxt->aidcs = aidc;
18601 else {
18602 aidc->next = vctxt->aidcs;
18603 vctxt->aidcs = aidc;
18604 }
18605}
18606
18607/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018608 * xmlSchemaIDCNewBinding:
18609 * @idcDef: the IDC definition of this binding
18610 *
18611 * Creates a new IDC binding.
18612 *
18613 * Returns the new binding in case of succeeded, NULL on internal errors.
18614 */
18615static xmlSchemaPSVIIDCBindingPtr
18616xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18617{
18618 xmlSchemaPSVIIDCBindingPtr ret;
18619
18620 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18621 sizeof(xmlSchemaPSVIIDCBinding));
18622 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018623 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018624 "allocating a PSVI IDC binding item", NULL);
18625 return (NULL);
18626 }
18627 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18628 ret->definition = idcDef;
18629 return (ret);
18630}
18631
18632/**
18633 * xmlSchemaIDCStoreNodeTableItem:
18634 * @vctxt: the WXS validation context
18635 * @item: the IDC node table item
18636 *
18637 * The validation context is used to store an IDC node table items.
18638 * They are stored to avoid copying them if IDC node-tables are merged
18639 * with corresponding parent IDC node-tables (bubbling).
18640 *
18641 * Returns 0 if succeeded, -1 on internal errors.
18642 */
18643static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018644xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018645 xmlSchemaPSVIIDCNodePtr item)
18646{
18647 /*
18648 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018649 */
18650 if (vctxt->idcNodes == NULL) {
18651 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018652 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18653 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018654 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018655 "allocating the IDC node table item list", NULL);
18656 return (-1);
18657 }
18658 vctxt->sizeIdcNodes = 20;
18659 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18660 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018661 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18662 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018663 sizeof(xmlSchemaPSVIIDCNodePtr));
18664 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018665 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018666 "re-allocating the IDC node table item list", NULL);
18667 return (-1);
18668 }
18669 }
18670 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018671
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018672 return (0);
18673}
18674
18675/**
18676 * xmlSchemaIDCStoreKey:
18677 * @vctxt: the WXS validation context
18678 * @item: the IDC key
18679 *
18680 * The validation context is used to store an IDC key.
18681 *
18682 * Returns 0 if succeeded, -1 on internal errors.
18683 */
18684static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018685xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018686 xmlSchemaPSVIIDCKeyPtr key)
18687{
18688 /*
18689 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018690 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018691 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018692 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018693 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18694 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018695 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018696 "allocating the IDC key storage list", NULL);
18697 return (-1);
18698 }
18699 vctxt->sizeIdcKeys = 40;
18700 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18701 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018702 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18703 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018704 sizeof(xmlSchemaPSVIIDCKeyPtr));
18705 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018706 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018707 "re-allocating the IDC key storage list", NULL);
18708 return (-1);
18709 }
18710 }
18711 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018712
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018713 return (0);
18714}
18715
18716/**
18717 * xmlSchemaIDCAppendNodeTableItem:
18718 * @bind: the IDC binding
18719 * @ntItem: the node-table item
18720 *
18721 * Appends the IDC node-table item to the binding.
18722 *
18723 * Returns 0 on success and -1 on internal errors.
18724 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018725static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018726xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18727 xmlSchemaPSVIIDCNodePtr ntItem)
18728{
18729 if (bind->nodeTable == NULL) {
18730 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018731 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018732 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18733 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018734 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018735 "allocating an array of IDC node-table items", NULL);
18736 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018737 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018738 } else if (bind->sizeNodes <= bind->nbNodes) {
18739 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018740 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18741 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018742 sizeof(xmlSchemaPSVIIDCNodePtr));
18743 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018744 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018745 "re-allocating an array of IDC node-table items", NULL);
18746 return(-1);
18747 }
18748 }
18749 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018750 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018751}
18752
18753/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018754 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018755 * @vctxt: the WXS validation context
18756 * @matcher: the IDC matcher
18757 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018758 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018759 * of the given matcher. If none found, a new one is created
18760 * and added to the IDC table.
18761 *
18762 * Returns an IDC binding or NULL on internal errors.
18763 */
18764static xmlSchemaPSVIIDCBindingPtr
18765xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18766 xmlSchemaIDCMatcherPtr matcher)
18767{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018768 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018769
18770 info = vctxt->elemInfos[matcher->depth];
18771
18772 if (info->idcTable == NULL) {
18773 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18774 if (info->idcTable == NULL)
18775 return (NULL);
18776 return(info->idcTable);
18777 } else {
18778 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018779
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018780 bind = info->idcTable;
18781 do {
18782 if (bind->definition == matcher->aidc->def)
18783 return(bind);
18784 if (bind->next == NULL) {
18785 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18786 if (bind->next == NULL)
18787 return (NULL);
18788 return(bind->next);
18789 }
18790 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018791 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018792 }
18793 return (NULL);
18794}
18795
18796/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018797 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018798 * @key: the IDC key
18799 *
18800 * Frees an IDC key together with its compiled value.
18801 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018802static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018803xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18804{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018805 if (key->val != NULL)
18806 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018807 xmlFree(key);
18808}
18809
18810/**
18811 * xmlSchemaIDCFreeBinding:
18812 *
18813 * Frees an IDC binding. Note that the node table-items
18814 * are not freed.
18815 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018816static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018817xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18818{
18819 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018820 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18821 int i;
18822 /*
18823 * Node-table items for keyrefs are not stored globally
18824 * to the validation context, since they are not bubbled.
18825 * We need to free them here.
18826 */
18827 for (i = 0; i < bind->nbNodes; i++) {
18828 xmlFree(bind->nodeTable[i]->keys);
18829 xmlFree(bind->nodeTable[i]);
18830 }
18831 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018832 xmlFree(bind->nodeTable);
18833 }
18834 xmlFree(bind);
18835}
18836
18837/**
18838 * xmlSchemaIDCFreeIDCTable:
18839 * @bind: the first IDC binding in the list
18840 *
18841 * Frees an IDC table, i.e. all the IDC bindings in the list.
18842 */
18843static void
18844xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18845{
18846 xmlSchemaPSVIIDCBindingPtr prev;
18847
18848 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018849 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018850 bind = bind->next;
18851 xmlSchemaIDCFreeBinding(prev);
18852 }
18853}
18854
18855/**
18856 * xmlSchemaIDCFreeMatcherList:
18857 * @matcher: the first IDC matcher in the list
18858 *
18859 * Frees a list of IDC matchers.
18860 */
18861static void
18862xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18863{
18864 xmlSchemaIDCMatcherPtr next;
18865
18866 while (matcher != NULL) {
18867 next = matcher->next;
18868 if (matcher->keySeqs != NULL) {
18869 int i;
18870 for (i = 0; i < matcher->sizeKeySeqs; i++)
18871 if (matcher->keySeqs[i] != NULL)
18872 xmlFree(matcher->keySeqs[i]);
18873 xmlFree(matcher->keySeqs);
18874 }
18875 xmlFree(matcher);
18876 matcher = next;
18877 }
18878}
18879
18880/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018881 * xmlSchemaIDCAddStateObject:
18882 * @vctxt: the WXS validation context
18883 * @matcher: the IDC matcher
18884 * @sel: the XPath information
18885 * @parent: the parent "selector" state object if any
18886 * @type: "selector" or "field"
18887 *
18888 * Creates/reuses and activates state objects for the given
18889 * XPath information; if the XPath expression consists of unions,
18890 * multiple state objects are created for every unioned expression.
18891 *
18892 * Returns 0 on success and -1 on internal errors.
18893 */
18894static int
18895xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18896 xmlSchemaIDCMatcherPtr matcher,
18897 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018898 int type)
18899{
18900 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018901
18902 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018903 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018904 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018905 if (vctxt->xpathStatePool != NULL) {
18906 sto = vctxt->xpathStatePool;
18907 vctxt->xpathStatePool = sto->next;
18908 sto->next = NULL;
18909 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018910 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018911 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018912 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018913 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18914 if (sto == NULL) {
18915 xmlSchemaVErrMemory(NULL,
18916 "allocating an IDC state object", NULL);
18917 return (-1);
18918 }
18919 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18920 }
18921 /*
18922 * Add to global list.
18923 */
18924 if (vctxt->xpathStates != NULL)
18925 sto->next = vctxt->xpathStates;
18926 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018927
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018928 /*
18929 * Free the old xpath validation context.
18930 */
18931 if (sto->xpathCtxt != NULL)
18932 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18933
18934 /*
18935 * Create a new XPath (pattern) validation context.
18936 */
18937 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18938 (xmlPatternPtr) sel->xpathComp);
18939 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018940 VERROR_INT("xmlSchemaIDCAddStateObject",
18941 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018942 return (-1);
18943 }
18944 sto->type = type;
18945 sto->depth = vctxt->depth;
18946 sto->matcher = matcher;
18947 sto->sel = sel;
18948 sto->nbHistory = 0;
18949
18950#if DEBUG_IDC
18951 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18952 sto->sel->xpath);
18953#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018954 return (0);
18955}
18956
18957/**
18958 * xmlSchemaXPathEvaluate:
18959 * @vctxt: the WXS validation context
18960 * @nodeType: the nodeType of the current node
18961 *
18962 * Evaluates all active XPath state objects.
18963 *
18964 * Returns the number of IC "field" state objects which resolved to
18965 * this node, 0 if none resolved and -1 on internal errors.
18966 */
18967static int
18968xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018969 xmlElementType nodeType)
18970{
18971 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018972 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018973
18974 if (vctxt->xpathStates == NULL)
18975 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018976
18977 if (nodeType == XML_ATTRIBUTE_NODE)
18978 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018979#if DEBUG_IDC
18980 {
18981 xmlChar *str = NULL;
18982 xmlGenericError(xmlGenericErrorContext,
18983 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018984 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18985 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018986 FREE_AND_NULL(str)
18987 }
18988#endif
18989 /*
18990 * Process all active XPath state objects.
18991 */
18992 first = vctxt->xpathStates;
18993 sto = first;
18994 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018995#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018996 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018997 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18998 sto->matcher->aidc->def->name, sto->sel->xpath);
18999 else
19000 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
19001 sto->matcher->aidc->def->name, sto->sel->xpath);
19002#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019003 if (nodeType == XML_ELEMENT_NODE)
19004 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019005 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019006 else
19007 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019008 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019009
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019010 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019011 VERROR_INT("xmlSchemaXPathEvaluate",
19012 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019013 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019014 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019015 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019016 goto next_sto;
19017 /*
19018 * Full match.
19019 */
19020#if DEBUG_IDC
19021 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019022 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019023#endif
19024 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019025 * Register a match in the state object history.
19026 */
19027 if (sto->history == NULL) {
19028 sto->history = (int *) xmlMalloc(5 * sizeof(int));
19029 if (sto->history == NULL) {
19030 xmlSchemaVErrMemory(NULL,
19031 "allocating the state object history", NULL);
19032 return(-1);
19033 }
19034 sto->sizeHistory = 10;
19035 } else if (sto->sizeHistory <= sto->nbHistory) {
19036 sto->sizeHistory *= 2;
19037 sto->history = (int *) xmlRealloc(sto->history,
19038 sto->sizeHistory * sizeof(int));
19039 if (sto->history == NULL) {
19040 xmlSchemaVErrMemory(NULL,
19041 "re-allocating the state object history", NULL);
19042 return(-1);
19043 }
19044 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019045 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019046
19047#ifdef DEBUG_IDC
19048 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19049 vctxt->depth);
19050#endif
19051
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019052 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19053 xmlSchemaIDCSelectPtr sel;
19054 /*
19055 * Activate state objects for the IDC fields of
19056 * the IDC selector.
19057 */
19058#if DEBUG_IDC
19059 xmlGenericError(xmlGenericErrorContext, "IDC: "
19060 "activating field states\n");
19061#endif
19062 sel = sto->matcher->aidc->def->fields;
19063 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019064 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19065 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19066 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019067 sel = sel->next;
19068 }
19069 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19070 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019071 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019072 */
19073#if DEBUG_IDC
19074 xmlGenericError(xmlGenericErrorContext,
19075 "IDC: key found\n");
19076#endif
19077 /*
19078 * Notify that the character value of this node is
19079 * needed.
19080 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019081 if (resolved == 0) {
19082 if ((vctxt->inode->flags &
19083 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19084 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19085 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019086 resolved++;
19087 }
19088next_sto:
19089 if (sto->next == NULL) {
19090 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019091 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019092 */
19093 head = first;
19094 sto = vctxt->xpathStates;
19095 } else
19096 sto = sto->next;
19097 }
19098 return (resolved);
19099}
19100
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019101static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019102xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019103 xmlChar **buf,
19104 xmlSchemaPSVIIDCKeyPtr *seq,
19105 int count)
19106{
19107 int i, res;
19108 const xmlChar *value = NULL;
19109
19110 *buf = xmlStrdup(BAD_CAST "[");
19111 for (i = 0; i < count; i++) {
19112 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019113 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19114 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019115 if (res == 0)
19116 *buf = xmlStrcat(*buf, value);
19117 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019118 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19119 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019120 *buf = xmlStrcat(*buf, BAD_CAST "???");
19121 }
19122 if (i < count -1)
19123 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19124 else
19125 *buf = xmlStrcat(*buf, BAD_CAST "'");
19126 if (value != NULL) {
19127 xmlFree((xmlChar *) value);
19128 value = NULL;
19129 }
19130 }
19131 *buf = xmlStrcat(*buf, BAD_CAST "]");
19132
19133 return (BAD_CAST *buf);
19134}
19135
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019136/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000019137 * xmlSchemaXPathPop:
19138 * @vctxt: the WXS validation context
19139 *
19140 * Pops all XPath states.
19141 *
19142 * Returns 0 on success and -1 on internal errors.
19143 */
19144static int
19145xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
19146{
19147 xmlSchemaIDCStateObjPtr sto;
19148 int res;
19149
19150 if (vctxt->xpathStates == NULL)
19151 return(0);
19152 sto = vctxt->xpathStates;
19153 do {
19154 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19155 if (res == -1)
19156 return (-1);
19157 sto = sto->next;
19158 } while (sto != NULL);
19159 return(0);
19160}
19161
19162/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019163 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019164 * @vctxt: the WXS validation context
19165 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019166 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019167 *
19168 * Processes and pops the history items of the IDC state objects.
19169 * IDC key-sequences are validated/created on IDC bindings.
19170 *
19171 * Returns 0 on success and -1 on internal errors.
19172 */
19173static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019174xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019175 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019176{
19177 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019178 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019179 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019180 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019181
19182 if (vctxt->xpathStates == NULL)
19183 return (0);
19184 sto = vctxt->xpathStates;
19185
19186#if DEBUG_IDC
19187 {
19188 xmlChar *str = NULL;
19189 xmlGenericError(xmlGenericErrorContext,
19190 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019191 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19192 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019193 FREE_AND_NULL(str)
19194 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019195#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019196 /*
19197 * Evaluate the state objects.
19198 */
19199 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019200 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19201 if (res == -1) {
19202 VERROR_INT("xmlSchemaXPathProcessHistory",
19203 "calling xmlStreamPop()");
19204 return (-1);
19205 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019206#if DEBUG_IDC
19207 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19208 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019209#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019210 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019211 goto deregister_check;
19212
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019213 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019214
19215 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019216 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019217 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019218 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019219 sto = sto->next;
19220 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019221 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019222 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19223 if (! IS_SIMPLE_TYPE(type)) {
19224 /*
19225 * Not qualified if the field resolves to a node of non
19226 * simple type.
19227 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019228 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19229 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019230 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19231 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019232 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019233
19234 sto->nbHistory--;
19235 goto deregister_check;
19236 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019237 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019238 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019239 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019240 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019241 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019242 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019243 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19244 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019245 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019246 sto->nbHistory--;
19247 goto deregister_check;
19248 } else {
19249 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19250 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019251 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019252
19253 /*
19254 * The key will be anchored on the matcher's list of
19255 * key-sequences. The position in this list is determined
19256 * by the target node's depth relative to the matcher's
19257 * depth of creation (i.e. the depth of the scope element).
19258 */
19259 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019260 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019261
19262 /*
19263 * Create/grow the array of key-sequences.
19264 */
19265 if (matcher->keySeqs == NULL) {
19266 if (pos > 9)
19267 matcher->sizeKeySeqs = pos * 2;
19268 else
19269 matcher->sizeKeySeqs = 10;
19270 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19271 xmlMalloc(matcher->sizeKeySeqs *
19272 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19273 if (matcher->keySeqs == NULL) {
19274 xmlSchemaVErrMemory(NULL,
19275 "allocating an array of key-sequences",
19276 NULL);
19277 return(-1);
19278 }
19279 memset(matcher->keySeqs, 0,
19280 matcher->sizeKeySeqs *
19281 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19282 } else if (pos >= matcher->sizeKeySeqs) {
19283 int i = matcher->sizeKeySeqs;
19284
19285 matcher->sizeKeySeqs *= 2;
19286 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19287 xmlRealloc(matcher->keySeqs,
19288 matcher->sizeKeySeqs *
19289 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019290 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019291 xmlSchemaVErrMemory(NULL,
19292 "reallocating an array of key-sequences",
19293 NULL);
19294 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019295 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019296 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019297 * The array needs to be NULLed.
19298 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019299 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019300 for (; i < matcher->sizeKeySeqs; i++)
19301 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019302 }
19303
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019304 /*
19305 * Get/create the key-sequence.
19306 */
19307 keySeq = matcher->keySeqs[pos];
19308 if (keySeq == NULL) {
19309 goto create_sequence;
19310 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019311 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019312 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019313 * cvc-identity-constraint:
19314 * 3 For each node in the ·target node set· all
19315 * of the {fields}, with that node as the context
19316 * node, evaluate to either an empty node-set or
19317 * a node-set with exactly one member, which must
19318 * have a simple type.
19319 *
19320 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019321 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019322 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19323 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019324 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019325 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019326 "with more than one member",
19327 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019328 sto->nbHistory--;
19329 goto deregister_check;
19330 } else {
19331 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019332 }
19333 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019334
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019335create_sequence:
19336 /*
19337 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019338 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019339 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19340 matcher->aidc->def->nbFields *
19341 sizeof(xmlSchemaPSVIIDCKeyPtr));
19342 if (keySeq == NULL) {
19343 xmlSchemaVErrMemory(NULL,
19344 "allocating an IDC key-sequence", NULL);
19345 return(-1);
19346 }
19347 memset(keySeq, 0, matcher->aidc->def->nbFields *
19348 sizeof(xmlSchemaPSVIIDCKeyPtr));
19349 matcher->keySeqs[pos] = keySeq;
19350create_key:
19351 /*
19352 * Created a key once per node only.
19353 */
19354 if (key == NULL) {
19355 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19356 sizeof(xmlSchemaPSVIIDCKey));
19357 if (key == NULL) {
19358 xmlSchemaVErrMemory(NULL,
19359 "allocating a IDC key", NULL);
19360 xmlFree(keySeq);
19361 matcher->keySeqs[pos] = NULL;
19362 return(-1);
19363 }
19364 /*
19365 * Consume the compiled value.
19366 */
19367 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019368 key->val = vctxt->inode->val;
19369 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019370 /*
19371 * Store the key in a global list.
19372 */
19373 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19374 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019375 return (-1);
19376 }
19377 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019378 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019379 }
19380 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019381
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019382 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19383 xmlSchemaPSVIIDCBindingPtr bind;
19384 xmlSchemaPSVIIDCNodePtr ntItem;
19385 xmlSchemaIDCMatcherPtr matcher;
19386 xmlSchemaIDCPtr idc;
19387 int pos, i, j, nbKeys;
19388 /*
19389 * Here we have the following scenario:
19390 * An IDC 'selector' state object resolved to a target node,
19391 * during the time this target node was in the
19392 * ancestor-or-self axis, the 'field' state object(s) looked
19393 * out for matching nodes to create a key-sequence for this
19394 * target node. Now we are back to this target node and need
19395 * to put the key-sequence, together with the target node
19396 * itself, into the node-table of the corresponding IDC
19397 * binding.
19398 */
19399 matcher = sto->matcher;
19400 idc = matcher->aidc->def;
19401 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019402 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019403 /*
19404 * Check if the matcher has any key-sequences at all, plus
19405 * if it has a key-sequence for the current target node.
19406 */
19407 if ((matcher->keySeqs == NULL) ||
19408 (matcher->sizeKeySeqs <= pos)) {
19409 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19410 goto selector_key_error;
19411 else
19412 goto selector_leave;
19413 }
19414
19415 keySeq = &(matcher->keySeqs[pos]);
19416 if (*keySeq == NULL) {
19417 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19418 goto selector_key_error;
19419 else
19420 goto selector_leave;
19421 }
19422
19423 for (i = 0; i < nbKeys; i++) {
19424 if ((*keySeq)[i] == NULL) {
19425 /*
19426 * Not qualified, if not all fields did resolve.
19427 */
19428 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19429 /*
19430 * All fields of a "key" IDC must resolve.
19431 */
19432 goto selector_key_error;
19433 }
19434 goto selector_leave;
19435 }
19436 }
19437 /*
19438 * All fields did resolve.
19439 */
19440
19441 /*
19442 * 4.1 If the {identity-constraint category} is unique(/key),
19443 * then no two members of the ·qualified node set· have
19444 * ·key-sequences· whose members are pairwise equal, as
19445 * defined by Equal in [XML Schemas: Datatypes].
19446 *
19447 * Get the IDC binding from the matcher and check for
19448 * duplicate key-sequences.
19449 */
19450 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19451 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19452 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019453 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019454
19455 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019456 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019457 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019458 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019459 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019460 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019461 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019462 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019463 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019464 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019465 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019466 if (res == -1) {
19467 return (-1);
19468 } else if (res == 0)
19469 break;
19470 }
19471 if (res == 1) {
19472 /*
19473 * Duplicate found.
19474 */
19475 break;
19476 }
19477 i++;
19478 } while (i < bind->nbNodes);
19479 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019480 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019481 /*
19482 * TODO: Try to report the key-sequence.
19483 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019484 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19485 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019486 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019487 "Duplicate key-sequence %s",
19488 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19489 (*keySeq), nbKeys), NULL);
19490 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019491 goto selector_leave;
19492 }
19493 }
19494 /*
19495 * Add a node-table item to the IDC binding.
19496 */
19497 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19498 sizeof(xmlSchemaPSVIIDCNode));
19499 if (ntItem == NULL) {
19500 xmlSchemaVErrMemory(NULL,
19501 "allocating an IDC node-table item", NULL);
19502 xmlFree(*keySeq);
19503 *keySeq = NULL;
19504 return(-1);
19505 }
19506 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19507
19508 /*
19509 * Store the node-table item on global list.
19510 */
19511 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19512 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19513 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019514 xmlFree(*keySeq);
19515 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019516 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019517 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019518 }
19519 /*
19520 * Init the node-table item. Consume the key-sequence.
19521 */
19522 ntItem->node = vctxt->node;
19523 ntItem->keys = *keySeq;
19524 *keySeq = NULL;
19525 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19526 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19527 /*
19528 * Free the item, since keyref items won't be
19529 * put on a global list.
19530 */
19531 xmlFree(ntItem->keys);
19532 xmlFree(ntItem);
19533 }
19534 return (-1);
19535 }
19536
19537 goto selector_leave;
19538selector_key_error:
19539 /*
19540 * 4.2.1 (KEY) The ·target node set· and the
19541 * ·qualified node set· are equal, that is, every
19542 * member of the ·target node set· is also a member
19543 * of the ·qualified node set· and vice versa.
19544 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019545 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19546 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019547selector_leave:
19548 /*
19549 * Free the key-sequence if not added to the IDC table.
19550 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019551 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019552 xmlFree(*keySeq);
19553 *keySeq = NULL;
19554 }
19555 } /* if selector */
19556
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019557 sto->nbHistory--;
19558
19559deregister_check:
19560 /*
19561 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019562 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019563 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019564#if DEBUG_IDC
19565 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19566 sto->sel->xpath);
19567#endif
19568 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019569 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019570 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019571 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019572 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019573 nextsto = sto->next;
19574 /*
19575 * Unlink from the list of active XPath state objects.
19576 */
19577 vctxt->xpathStates = sto->next;
19578 sto->next = vctxt->xpathStatePool;
19579 /*
19580 * Link it to the pool of reusable state objects.
19581 */
19582 vctxt->xpathStatePool = sto;
19583 sto = nextsto;
19584 } else
19585 sto = sto->next;
19586 } /* while (sto != NULL) */
19587 return (0);
19588}
19589
19590/**
19591 * xmlSchemaIDCRegisterMatchers:
19592 * @vctxt: the WXS validation context
19593 * @elemDecl: the element declaration
19594 *
19595 * Creates helper objects to evaluate IDC selectors/fields
19596 * successively.
19597 *
19598 * Returns 0 if OK and -1 on internal errors.
19599 */
19600static int
19601xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19602 xmlSchemaElementPtr elemDecl)
19603{
19604 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19605 xmlSchemaIDCPtr idc, refIdc;
19606 xmlSchemaIDCAugPtr aidc;
19607
19608 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19609 if (idc == NULL)
19610 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019611
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019612#if DEBUG_IDC
19613 {
19614 xmlChar *str = NULL;
19615 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019616 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019617 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19618 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019619 FREE_AND_NULL(str)
19620 }
19621#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019622 if (vctxt->inode->idcMatchers != NULL) {
19623 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19624 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019625 return (-1);
19626 }
19627 do {
19628 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19629 /*
19630 * Since IDCs bubbles are expensive we need to know the
19631 * depth at which the bubbles should stop; this will be
19632 * the depth of the top-most keyref IDC. If no keyref
19633 * references a key/unique IDC, the bubbleDepth will
19634 * be -1, indicating that no bubbles are needed.
19635 */
19636 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19637 if (refIdc != NULL) {
19638 /*
19639 * Lookup the augmented IDC.
19640 */
19641 aidc = vctxt->aidcs;
19642 while (aidc != NULL) {
19643 if (aidc->def == refIdc)
19644 break;
19645 aidc = aidc->next;
19646 }
19647 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019648 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019649 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019650 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019651 return (-1);
19652 }
19653 if ((aidc->bubbleDepth == -1) ||
19654 (vctxt->depth < aidc->bubbleDepth))
19655 aidc->bubbleDepth = vctxt->depth;
19656 }
19657 }
19658 /*
19659 * Lookup the augmented IDC item for the IDC definition.
19660 */
19661 aidc = vctxt->aidcs;
19662 while (aidc != NULL) {
19663 if (aidc->def == idc)
19664 break;
19665 aidc = aidc->next;
19666 }
19667 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019668 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19669 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019670 return (-1);
19671 }
19672 /*
19673 * Create an IDC matcher for every IDC definition.
19674 */
19675 matcher = (xmlSchemaIDCMatcherPtr)
19676 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19677 if (matcher == NULL) {
19678 xmlSchemaVErrMemory(vctxt,
19679 "allocating an IDC matcher", NULL);
19680 return (-1);
19681 }
19682 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19683 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019684 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019685 else
19686 last->next = matcher;
19687 last = matcher;
19688
19689 matcher->type = IDC_MATCHER;
19690 matcher->depth = vctxt->depth;
19691 matcher->aidc = aidc;
19692#if DEBUG_IDC
19693 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19694#endif
19695 /*
19696 * Init the automaton state object.
19697 */
19698 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019699 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019700 return (-1);
19701
19702 idc = idc->next;
19703 } while (idc != NULL);
19704 return (0);
19705}
19706
19707/**
19708 * xmlSchemaBubbleIDCNodeTables:
19709 * @depth: the current tree depth
19710 *
19711 * Merges IDC bindings of an element at @depth into the corresponding IDC
19712 * bindings of its parent element. If a duplicate note-table entry is found,
19713 * both, the parent node-table entry and child entry are discarded from the
19714 * node-table of the parent.
19715 *
19716 * Returns 0 if OK and -1 on internal errors.
19717 */
19718static int
19719xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19720{
19721 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019722 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19723 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019724 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19725 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019726 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019727 int duplTop;
19728
19729 /*
19730 * The node table has the following sections:
19731 *
19732 * O --> old node-table entries (first)
19733 * O
19734 * + --> new node-table entries
19735 * +
19736 * % --> new duplicate node-table entries
19737 * %
19738 * # --> old duplicate node-table entries
19739 * # (last)
19740 *
19741 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019742 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019743 if (bind == NULL) {
19744 /* Fine, no table, no bubbles. */
19745 return (0);
19746 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019747
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019748 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19749 /*
19750 * Walk all bindings; create new or add to existing bindings.
19751 * Remove duplicate key-sequences.
19752 */
19753start_binding:
19754 while (bind != NULL) {
19755 /*
19756 * Skip keyref IDCs.
19757 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019758 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19759 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019760 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019761 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019762 /*
19763 * Check if the key/unique IDC table needs to be bubbled.
19764 */
19765 aidc = vctxt->aidcs;
19766 do {
19767 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019768 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019769 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019770 bind = bind->next;
19771 goto start_binding;
19772 }
19773 break;
19774 }
19775 aidc = aidc->next;
19776 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019777
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019778 if (parTable != NULL)
19779 parBind = *parTable;
19780 while (parBind != NULL) {
19781 /*
19782 * Search a matching parent binding for the
19783 * IDC definition.
19784 */
19785 if (parBind->definition == bind->definition) {
19786
19787 /*
19788 * Compare every node-table entry of the child node,
19789 * i.e. the key-sequence within, ...
19790 */
19791 oldNum = parBind->nbNodes; /* Skip newly added items. */
19792 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019793 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019794
19795 for (i = 0; i < bind->nbNodes; i++) {
19796 node = bind->nodeTable[i];
19797 if (node == NULL)
19798 continue;
19799 /*
19800 * ...with every key-sequence of the parent node, already
19801 * evaluated to be a duplicate key-sequence.
19802 */
19803 if (parBind->nbDupls != 0) {
19804 j = bind->nbNodes + newDupls;
19805 while (j < duplTop) {
19806 parNode = parBind->nodeTable[j];
19807 for (k = 0; k < bind->definition->nbFields; k++) {
19808 key = node->keys[k];
19809 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019810 ret = xmlSchemaAreValuesEqual(key->val,
19811 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019812 if (ret == -1) {
19813 /* TODO: Internal error */
19814 return(-1);
19815 } else if (ret == 0)
19816 break;
19817
19818 }
19819 if (ret == 1)
19820 /* Duplicate found. */
19821 break;
19822 j++;
19823 }
19824 if (j != duplTop) {
19825 /* Duplicate found. */
19826 continue;
19827 }
19828 }
19829 /*
19830 * ... and with every key-sequence of the parent node.
19831 */
19832 j = 0;
19833 while (j < oldNum) {
19834 parNode = parBind->nodeTable[j];
19835 /*
19836 * Compare key by key.
19837 */
19838 for (k = 0; k < parBind->definition->nbFields; k++) {
19839 key = node->keys[k];
19840 parKey = parNode->keys[k];
19841
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019842 ret = xmlSchemaAreValuesEqual(key->val,
19843 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019844 if (ret == -1) {
19845 /* TODO: Internal error */
19846 } else if (ret == 0)
19847 break;
19848
19849 }
19850 if (ret == 1)
19851 /*
19852 * The key-sequences are equal.
19853 */
19854 break;
19855 j++;
19856 }
19857 if (j != oldNum) {
19858 /*
19859 * Handle duplicates.
19860 */
19861 newDupls++;
19862 oldNum--;
19863 parBind->nbNodes--;
19864 /*
19865 * Move last old item to pos of duplicate.
19866 */
19867 parBind->nodeTable[j] =
19868 parBind->nodeTable[oldNum];
19869
19870 if (parBind->nbNodes != oldNum) {
19871 /*
19872 * If new items exist, move last new item to
19873 * last of old items.
19874 */
19875 parBind->nodeTable[oldNum] =
19876 parBind->nodeTable[parBind->nbNodes];
19877 }
19878 /*
19879 * Move duplicate to last pos of new/old items.
19880 */
19881 parBind->nodeTable[parBind->nbNodes] = parNode;
19882
19883 } else {
19884 /*
19885 * Add the node-table entry (node and key-sequence) of
19886 * the child node to the node table of the parent node.
19887 */
19888 if (parBind->nodeTable == NULL) {
19889 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019890 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019891 if (parBind->nodeTable == NULL) {
19892 xmlSchemaVErrMemory(NULL,
19893 "allocating IDC list of node-table items", NULL);
19894 return(-1);
19895 }
19896 parBind->sizeNodes = 1;
19897 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019898 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019899 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19900 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19901 sizeof(xmlSchemaPSVIIDCNodePtr));
19902 if (parBind->nodeTable == NULL) {
19903 xmlSchemaVErrMemory(NULL,
19904 "re-allocating IDC list of node-table items", NULL);
19905 return(-1);
19906 }
19907 }
19908
19909 /*
19910 * Move first old duplicate to last position
19911 * of old duplicates +1.
19912 */
19913 if (parBind->nbDupls != 0) {
19914 parBind->nodeTable[duplTop] =
19915 parBind->nodeTable[parBind->nbNodes + newDupls];
19916 }
19917 /*
19918 * Move first new duplicate to last position of
19919 * new duplicates +1.
19920 */
19921 if (newDupls != 0) {
19922 parBind->nodeTable[parBind->nbNodes + newDupls] =
19923 parBind->nodeTable[parBind->nbNodes];
19924 }
19925 /*
19926 * Append the new node-table entry to the 'new node-table
19927 * entries' section.
19928 */
19929 parBind->nodeTable[parBind->nbNodes] = node;
19930 parBind->nbNodes++;
19931 duplTop++;
19932 }
19933 }
19934 parBind->nbDupls += newDupls;
19935 break;
19936 }
19937 if (parBind->next == NULL)
19938 lastParBind = parBind;
19939 parBind = parBind->next;
19940 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019941 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019942 /*
19943 * No binding for the IDC was found: create a new one and
19944 * copy all node-tables.
19945 */
19946 parBind = xmlSchemaIDCNewBinding(bind->definition);
19947 if (parBind == NULL)
19948 return(-1);
19949
19950 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19951 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19952 if (parBind->nodeTable == NULL) {
19953 xmlSchemaVErrMemory(NULL,
19954 "allocating an array of IDC node-table items", NULL);
19955 xmlSchemaIDCFreeBinding(parBind);
19956 return(-1);
19957 }
19958 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019959 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019960 memcpy(parBind->nodeTable, bind->nodeTable,
19961 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019962 if (*parTable == NULL)
19963 *parTable = parBind;
19964 else
19965 lastParBind->next = parBind;
19966 }
19967 bind = bind->next;
19968 }
19969 return (0);
19970}
19971
19972/**
19973 * xmlSchemaCheckCVCIDCKeyRef:
19974 * @vctxt: the WXS validation context
19975 * @elemDecl: the element declaration
19976 *
19977 * Check the cvc-idc-keyref constraints.
19978 */
19979static int
19980xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19981{
19982 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19983
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019984 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019985 /*
19986 * Find a keyref.
19987 */
19988 while (refbind != NULL) {
19989 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19990 int i, j, k, res;
19991 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19992 xmlSchemaPSVIIDCKeyPtr refKey, key;
19993
19994 /*
19995 * Find the referred key/unique.
19996 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019997 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019998 do {
19999 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
20000 bind->definition)
20001 break;
20002 bind = bind->next;
20003 } while (bind != NULL);
20004
20005 /*
20006 * Search for a matching key-sequences.
20007 */
20008 for (i = 0; i < refbind->nbNodes; i++) {
20009 res = 0;
20010 if (bind != NULL) {
20011 refKeys = refbind->nodeTable[i]->keys;
20012 for (j = 0; j < bind->nbNodes; j++) {
20013 keys = bind->nodeTable[j]->keys;
20014 for (k = 0; k < bind->definition->nbFields; k++) {
20015 refKey = refKeys[k];
20016 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020017 res = xmlSchemaAreValuesEqual(key->val,
20018 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020019 if (res == 0)
20020 break;
20021 else if (res == -1) {
20022 return (-1);
20023 }
20024 }
20025 if (res == 1) {
20026 /*
20027 * Match found.
20028 */
20029 break;
20030 }
20031 }
20032 }
20033 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020034 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020035 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020036 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20037 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020038 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020039 "No match found for key-sequence %s of key "
20040 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020041 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020042 refbind->nodeTable[i]->keys,
20043 refbind->definition->nbFields),
20044 xmlSchemaFormatQName(&strB,
20045 refbind->definition->targetNamespace,
20046 refbind->definition->name));
20047 FREE_AND_NULL(str);
20048 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020049 }
20050 }
20051 }
20052 refbind = refbind->next;
20053 }
20054 return (0);
20055}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020056
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020057/************************************************************************
20058 * *
20059 * XML Reader validation code *
20060 * *
20061 ************************************************************************/
20062
20063static xmlSchemaAttrInfoPtr
20064xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020065{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020066 xmlSchemaAttrInfoPtr iattr;
20067 /*
20068 * Grow/create list of attribute infos.
20069 */
20070 if (vctxt->attrInfos == NULL) {
20071 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20072 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
20073 vctxt->sizeAttrInfos = 1;
20074 if (vctxt->attrInfos == NULL) {
20075 xmlSchemaVErrMemory(vctxt,
20076 "allocating attribute info list", NULL);
20077 return (NULL);
20078 }
20079 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
20080 vctxt->sizeAttrInfos++;
20081 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20082 xmlRealloc(vctxt->attrInfos,
20083 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
20084 if (vctxt->attrInfos == NULL) {
20085 xmlSchemaVErrMemory(vctxt,
20086 "re-allocating attribute info list", NULL);
20087 return (NULL);
20088 }
20089 } else {
20090 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
20091 if (iattr->localName != NULL) {
20092 VERROR_INT("xmlSchemaGetFreshAttrInfo",
20093 "attr info not cleared");
20094 return (NULL);
20095 }
20096 iattr->nodeType = XML_ATTRIBUTE_NODE;
20097 return (iattr);
20098 }
20099 /*
20100 * Create an attribute info.
20101 */
20102 iattr = (xmlSchemaAttrInfoPtr)
20103 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20104 if (iattr == NULL) {
20105 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20106 return (NULL);
20107 }
20108 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20109 iattr->nodeType = XML_ATTRIBUTE_NODE;
20110 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20111
20112 return (iattr);
20113}
20114
20115static int
20116xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20117 xmlNodePtr attrNode,
20118 const xmlChar *localName,
20119 const xmlChar *nsName,
20120 int ownedNames,
20121 xmlChar *value,
20122 int ownedValue)
20123{
20124 xmlSchemaAttrInfoPtr attr;
20125
20126 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20127 if (attr == NULL) {
20128 VERROR_INT("xmlSchemaPushAttribute",
20129 "calling xmlSchemaGetFreshAttrInfo()");
20130 return (-1);
20131 }
20132 attr->node = attrNode;
20133 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20134 attr->localName = localName;
20135 attr->nsName = nsName;
20136 if (ownedNames)
20137 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20138 /*
20139 * Evaluate if it's an XSI attribute.
20140 */
20141 if (nsName != NULL) {
20142 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20143 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20144 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20145 }
20146 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20147 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20148 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20149 }
20150 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20151 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20152 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20153 }
20154 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20155 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20156 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20157 }
20158 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20159 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20160 }
20161 }
20162 attr->value = value;
20163 if (ownedValue)
20164 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20165 if (attr->metaType != 0)
20166 attr->state = XML_SCHEMAS_ATTR_META;
20167 return (0);
20168}
20169
20170static void
20171xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20172{
20173 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20174 FREE_AND_NULL(ielem->localName);
20175 FREE_AND_NULL(ielem->nsName);
20176 } else {
20177 ielem->localName = NULL;
20178 ielem->nsName = NULL;
20179 }
20180 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20181 FREE_AND_NULL(ielem->value);
20182 } else {
20183 ielem->value = NULL;
20184 }
20185 if (ielem->val != NULL) {
20186 xmlSchemaFreeValue(ielem->val);
20187 ielem->val = NULL;
20188 }
20189 if (ielem->idcMatchers != NULL) {
20190 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20191 ielem->idcMatchers = NULL;
20192 }
20193 if (ielem->idcTable != NULL) {
20194 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20195 ielem->idcTable = NULL;
20196 }
20197 if (ielem->regexCtxt != NULL) {
20198 xmlRegFreeExecCtxt(ielem->regexCtxt);
20199 ielem->regexCtxt = NULL;
20200 }
20201 if (ielem->nsBindings != NULL) {
20202 xmlFree((xmlChar **)ielem->nsBindings);
20203 ielem->nsBindings = NULL;
20204 ielem->nbNsBindings = 0;
20205 ielem->sizeNsBindings = 0;
20206 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020207}
20208
20209/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020210 * xmlSchemaGetFreshElemInfo:
20211 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020212 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020213 * Creates/reuses and initializes the element info item for
20214 * the currect tree depth.
20215 *
20216 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020217 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020218static xmlSchemaNodeInfoPtr
20219xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020220{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020221 xmlSchemaNodeInfoPtr info = NULL;
20222
20223 if (vctxt->depth > vctxt->sizeElemInfos) {
20224 VERROR_INT("xmlSchemaGetFreshElemInfo",
20225 "inconsistent depth encountered");
20226 return (NULL);
20227 }
20228 if (vctxt->elemInfos == NULL) {
20229 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20230 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20231 if (vctxt->elemInfos == NULL) {
20232 xmlSchemaVErrMemory(vctxt,
20233 "allocating the element info array", NULL);
20234 return (NULL);
20235 }
20236 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20237 vctxt->sizeElemInfos = 10;
20238 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20239 int i = vctxt->sizeElemInfos;
20240
20241 vctxt->sizeElemInfos *= 2;
20242 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20243 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20244 sizeof(xmlSchemaNodeInfoPtr));
20245 if (vctxt->elemInfos == NULL) {
20246 xmlSchemaVErrMemory(vctxt,
20247 "re-allocating the element info array", NULL);
20248 return (NULL);
20249 }
20250 /*
20251 * We need the new memory to be NULLed.
20252 * TODO: Use memset instead?
20253 */
20254 for (; i < vctxt->sizeElemInfos; i++)
20255 vctxt->elemInfos[i] = NULL;
20256 } else
20257 info = vctxt->elemInfos[vctxt->depth];
20258
20259 if (info == NULL) {
20260 info = (xmlSchemaNodeInfoPtr)
20261 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20262 if (info == NULL) {
20263 xmlSchemaVErrMemory(vctxt,
20264 "allocating an element info", NULL);
20265 return (NULL);
20266 }
20267 vctxt->elemInfos[vctxt->depth] = info;
20268 } else {
20269 if (info->localName != NULL) {
20270 VERROR_INT("xmlSchemaGetFreshElemInfo",
20271 "elem info has not been cleared");
20272 return (NULL);
20273 }
20274 }
20275 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20276 info->nodeType = XML_ELEMENT_NODE;
20277 info->depth = vctxt->depth;
20278
20279 return (info);
20280}
20281
20282#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20283#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20284#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20285
20286static int
20287xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20288 xmlNodePtr node,
20289 xmlSchemaTypePtr type,
20290 xmlSchemaValType valType,
20291 const xmlChar * value,
20292 xmlSchemaValPtr val,
20293 unsigned long length,
20294 int fireErrors)
20295{
20296 int ret, error = 0;
20297
20298 xmlSchemaTypePtr tmpType;
20299 xmlSchemaFacetLinkPtr facetLink;
20300 xmlSchemaFacetPtr facet;
20301 unsigned long len = 0;
20302 xmlSchemaWhitespaceValueType ws;
20303
20304 /*
20305 * In Libxml2, derived built-in types have currently no explicit facets.
20306 */
20307 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020308 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020309
20310 /*
20311 * NOTE: Do not jump away, if the facetSet of the given type is
20312 * empty: until now, "pattern" and "enumeration" facets of the
20313 * *base types* need to be checked as well.
20314 */
20315 if (type->facetSet == NULL)
20316 goto pattern_and_enum;
20317
20318 if (! VARIETY_ATOMIC(type)) {
20319 if (VARIETY_LIST(type))
20320 goto variety_list;
20321 else
20322 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020323 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020324 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020325 * Whitespace handling is only of importance for string-based
20326 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020327 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020328 tmpType = xmlSchemaGetPrimitiveType(type);
20329 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20330 IS_ANY_SIMPLE_TYPE(tmpType)) {
20331 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20332 } else
20333 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20334 /*
20335 * If the value was not computed (for string or
20336 * anySimpleType based types), then use the provided
20337 * type.
20338 */
20339 if (val == NULL)
20340 valType = valType;
20341 else
20342 valType = xmlSchemaGetValType(val);
20343
20344 ret = 0;
20345 for (facetLink = type->facetSet; facetLink != NULL;
20346 facetLink = facetLink->next) {
20347 /*
20348 * Skip the pattern "whiteSpace": it is used to
20349 * format the character content beforehand.
20350 */
20351 switch (facetLink->facet->type) {
20352 case XML_SCHEMA_FACET_WHITESPACE:
20353 case XML_SCHEMA_FACET_PATTERN:
20354 case XML_SCHEMA_FACET_ENUMERATION:
20355 continue;
20356 case XML_SCHEMA_FACET_LENGTH:
20357 case XML_SCHEMA_FACET_MINLENGTH:
20358 case XML_SCHEMA_FACET_MAXLENGTH:
20359 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20360 valType, value, val, &len, ws);
20361 break;
20362 default:
20363 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20364 valType, value, val, ws);
20365 break;
20366 }
20367 if (ret < 0) {
20368 AERROR_INT("xmlSchemaValidateFacets",
20369 "validating against a atomic type facet");
20370 return (-1);
20371 } else if (ret > 0) {
20372 if (fireErrors)
20373 xmlSchemaFacetErr(actxt, ret, node,
20374 value, len, type, facetLink->facet, NULL, NULL, NULL);
20375 else
20376 return (ret);
20377 if (error == 0)
20378 error = ret;
20379 }
20380 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020381 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020382
20383variety_list:
20384 if (! VARIETY_LIST(type))
20385 goto pattern_and_enum;
20386 /*
20387 * "length", "minLength" and "maxLength" of list types.
20388 */
20389 ret = 0;
20390 for (facetLink = type->facetSet; facetLink != NULL;
20391 facetLink = facetLink->next) {
20392
20393 switch (facetLink->facet->type) {
20394 case XML_SCHEMA_FACET_LENGTH:
20395 case XML_SCHEMA_FACET_MINLENGTH:
20396 case XML_SCHEMA_FACET_MAXLENGTH:
20397 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20398 value, length, NULL);
20399 break;
20400 default:
20401 continue;
20402 }
20403 if (ret < 0) {
20404 AERROR_INT("xmlSchemaValidateFacets",
20405 "validating against a list type facet");
20406 return (-1);
20407 } else if (ret > 0) {
20408 if (fireErrors)
20409 xmlSchemaFacetErr(actxt, ret, node,
20410 value, length, type, facetLink->facet, NULL, NULL, NULL);
20411 else
20412 return (ret);
20413 if (error == 0)
20414 error = ret;
20415 }
20416 ret = 0;
20417 }
20418
20419pattern_and_enum:
20420 if (error >= 0) {
20421 int found = 0;
20422 /*
20423 * Process enumerations. Facet values are in the value space
20424 * of the defining type's base type. This seems to be a bug in the
20425 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20426 * Only the first set of enumerations in the ancestor-or-self axis
20427 * is used for validation.
20428 */
20429 ret = 0;
20430 tmpType = type;
20431 do {
20432 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20433 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20434 continue;
20435 found = 1;
20436 ret = xmlSchemaAreValuesEqual(facet->val, val);
20437 if (ret == 1)
20438 break;
20439 else if (ret < 0) {
20440 AERROR_INT("xmlSchemaValidateFacets",
20441 "validating against an enumeration facet");
20442 return (-1);
20443 }
20444 }
20445 if (ret != 0)
20446 break;
20447 tmpType = tmpType->baseType;
20448 } while ((tmpType != NULL) &&
20449 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20450 if (found && (ret == 0)) {
20451 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20452 if (fireErrors) {
20453 xmlSchemaFacetErr(actxt, ret, node,
20454 value, 0, type, NULL, NULL, NULL, NULL);
20455 } else
20456 return (ret);
20457 if (error == 0)
20458 error = ret;
20459 }
20460 }
20461
20462 if (error >= 0) {
20463 int found;
20464 /*
20465 * Process patters. Pattern facets are ORed at type level
20466 * and ANDed if derived. Walk the base type axis.
20467 */
20468 tmpType = type;
20469 facet = NULL;
20470 do {
20471 found = 0;
20472 for (facetLink = tmpType->facetSet; facetLink != NULL;
20473 facetLink = facetLink->next) {
20474 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20475 continue;
20476 found = 1;
20477 /*
20478 * NOTE that for patterns, @value needs to be the
20479 * normalized vaule.
20480 */
20481 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20482 if (ret == 1)
20483 break;
20484 else if (ret < 0) {
20485 AERROR_INT("xmlSchemaValidateFacets",
20486 "validating against a pattern facet");
20487 return (-1);
20488 } else {
20489 /*
20490 * Save the last non-validating facet.
20491 */
20492 facet = facetLink->facet;
20493 }
20494 }
20495 if (found && (ret != 1)) {
20496 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20497 if (fireErrors) {
20498 xmlSchemaFacetErr(actxt, ret, node,
20499 value, 0, type, facet, NULL, NULL, NULL);
20500 } else
20501 return (ret);
20502 if (error == 0)
20503 error = ret;
20504 break;
20505 }
20506 tmpType = tmpType->baseType;
20507 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20508 }
20509
20510 return (error);
20511}
20512
20513static xmlChar *
20514xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20515 const xmlChar *value)
20516{
20517 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20518 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20519 return (xmlSchemaCollapseString(value));
20520 case XML_SCHEMA_WHITESPACE_REPLACE:
20521 return (xmlSchemaWhiteSpaceReplace(value));
20522 default:
20523 return (NULL);
20524 }
20525}
20526
20527static int
20528xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20529 const xmlChar *value,
20530 xmlSchemaValPtr *val,
20531 int valNeeded)
20532{
20533 int ret;
20534 const xmlChar *nsName;
20535 xmlChar *local, *prefix = NULL;
20536
20537 ret = xmlValidateQName(value, 1);
20538 if (ret != 0) {
20539 if (ret == -1) {
20540 VERROR_INT("xmlSchemaValidateQName",
20541 "calling xmlValidateQName()");
20542 return (-1);
20543 }
20544 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20545 }
20546 /*
20547 * NOTE: xmlSplitQName2 will always return a duplicated
20548 * strings.
20549 */
20550 local = xmlSplitQName2(value, &prefix);
20551 if (local == NULL)
20552 local = xmlStrdup(value);
20553 /*
20554 * OPTIMIZE TODO: Use flags for:
20555 * - is there any namespace binding?
20556 * - is there a default namespace?
20557 */
20558 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20559
20560 if (prefix != NULL) {
20561 xmlFree(prefix);
20562 /*
20563 * A namespace must be found if the prefix is
20564 * NOT NULL.
20565 */
20566 if (nsName == NULL) {
20567 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20568 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20569 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20570 "The QName value '%s' has no "
20571 "corresponding namespace declaration in "
20572 "scope", value, NULL);
20573 if (local != NULL)
20574 xmlFree(local);
20575 return (ret);
20576 }
20577 }
20578 if (valNeeded && val) {
20579 if (nsName != NULL)
20580 *val = xmlSchemaNewQNameValue(
20581 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20582 else
20583 *val = xmlSchemaNewQNameValue(NULL,
20584 BAD_CAST local);
20585 } else
20586 xmlFree(local);
20587 return (0);
20588}
20589
20590/*
20591* cvc-simple-type
20592*/
20593static int
20594xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20595 xmlNodePtr node,
20596 xmlSchemaTypePtr type,
20597 const xmlChar *value,
20598 xmlSchemaValPtr *retVal,
20599 int fireErrors,
20600 int normalize,
20601 int isNormalized)
20602{
20603 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20604 xmlSchemaValPtr val = NULL;
20605 xmlSchemaWhitespaceValueType ws;
20606 xmlChar *normValue = NULL;
20607
20608#define NORMALIZE(atype) \
20609 if ((! isNormalized) && \
20610 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20611 normValue = xmlSchemaNormalizeValue(atype, value); \
20612 if (normValue != NULL) \
20613 value = normValue; \
20614 isNormalized = 1; \
20615 }
20616
20617 if ((retVal != NULL) && (*retVal != NULL)) {
20618 xmlSchemaFreeValue(*retVal);
20619 *retVal = NULL;
20620 }
20621 /*
20622 * 3.14.4 Simple Type Definition Validation Rules
20623 * Validation Rule: String Valid
20624 */
20625 /*
20626 * 1 It is schema-valid with respect to that definition as defined
20627 * by Datatype Valid in [XML Schemas: Datatypes].
20628 */
20629 /*
20630 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20631 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20632 * the string must be a ·declared entity name·.
20633 */
20634 /*
20635 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20636 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20637 * then every whitespace-delimited substring of the string must be a ·declared
20638 * entity name·.
20639 */
20640 /*
20641 * 2.3 otherwise no further condition applies.
20642 */
20643 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20644 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020645 if (value == NULL)
20646 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020647 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20648 xmlSchemaTypePtr biType; /* The built-in type. */
20649 /*
20650 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20651 * a literal in the ·lexical space· of {base type definition}"
20652 */
20653 /*
20654 * Whitespace-normalize.
20655 */
20656 NORMALIZE(type);
20657 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20658 /*
20659 * Get the built-in type.
20660 */
20661 biType = type->baseType;
20662 while ((biType != NULL) &&
20663 (biType->type != XML_SCHEMA_TYPE_BASIC))
20664 biType = biType->baseType;
20665
20666 if (biType == NULL) {
20667 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20668 "could not get the built-in type");
20669 goto internal_error;
20670 }
20671 } else
20672 biType = type;
20673 /*
20674 * NOTATIONs need to be processed here, since they need
20675 * to lookup in the hashtable of NOTATION declarations of the schema.
20676 */
20677 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20678 switch (biType->builtInType) {
20679 case XML_SCHEMAS_NOTATION:
20680 ret = xmlSchemaValidateNotation(
20681 (xmlSchemaValidCtxtPtr) actxt,
20682 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20683 NULL, value, &val, valNeeded);
20684 break;
20685 case XML_SCHEMAS_QNAME:
20686 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20687 value, &val, valNeeded);
20688 break;
20689 default:
20690 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20691 if (valNeeded)
20692 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20693 value, &val, NULL);
20694 else
20695 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20696 value, NULL, NULL);
20697 break;
20698 }
20699 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20700 switch (biType->builtInType) {
20701 case XML_SCHEMAS_NOTATION:
20702 ret = xmlSchemaValidateNotation(NULL,
20703 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20704 value, &val, valNeeded);
20705 break;
20706 default:
20707 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20708 if (valNeeded)
20709 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20710 value, &val, node);
20711 else
20712 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20713 value, NULL, node);
20714 break;
20715 }
20716 } else {
20717 /*
20718 * Validation via a public API is not implemented yet.
20719 */
20720 TODO
20721 goto internal_error;
20722 }
20723 if (ret != 0) {
20724 if (ret < 0) {
20725 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20726 "validating against a built-in type");
20727 goto internal_error;
20728 }
20729 if (VARIETY_LIST(type))
20730 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20731 else
20732 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20733 }
20734 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20735 /*
20736 * Check facets.
20737 */
20738 ret = xmlSchemaValidateFacets(actxt, node, type,
20739 (xmlSchemaValType) biType->builtInType, value, val,
20740 0, fireErrors);
20741 if (ret != 0) {
20742 if (ret < 0) {
20743 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20744 "validating facets of atomic simple type");
20745 goto internal_error;
20746 }
20747 if (VARIETY_LIST(type))
20748 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20749 else
20750 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20751 }
20752 }
20753 if (fireErrors && (ret > 0))
20754 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20755 } else if (VARIETY_LIST(type)) {
20756
20757 xmlSchemaTypePtr itemType;
20758 const xmlChar *cur, *end;
20759 xmlChar *tmpValue = NULL;
20760 unsigned long len = 0;
20761 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20762 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20763 * of white space separated tokens, each of which ·match·es a literal
20764 * in the ·lexical space· of {item type definition}
20765 */
20766 /*
20767 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20768 * the list type has an enum or pattern facet.
20769 */
20770 NORMALIZE(type);
20771 /*
20772 * VAL TODO: Optimize validation of empty values.
20773 * VAL TODO: We do not have computed values for lists.
20774 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020775 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020776 cur = value;
20777 do {
20778 while (IS_BLANK_CH(*cur))
20779 cur++;
20780 end = cur;
20781 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20782 end++;
20783 if (end == cur)
20784 break;
20785 tmpValue = xmlStrndup(cur, end - cur);
20786 len++;
20787
20788 if (valNeeded)
20789 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20790 tmpValue, &curVal, fireErrors, 0, 1);
20791 else
20792 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20793 tmpValue, NULL, fireErrors, 0, 1);
20794 FREE_AND_NULL(tmpValue);
20795 if (curVal != NULL) {
20796 /*
20797 * Add to list of computed values.
20798 */
20799 if (val == NULL)
20800 val = curVal;
20801 else
20802 xmlSchemaValueAppend(prevVal, curVal);
20803 prevVal = curVal;
20804 curVal = NULL;
20805 }
20806 if (ret != 0) {
20807 if (ret < 0) {
20808 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20809 "validating an item of list simple type");
20810 goto internal_error;
20811 }
20812 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20813 break;
20814 }
20815 cur = end;
20816 } while (*cur != 0);
20817 FREE_AND_NULL(tmpValue);
20818 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20819 /*
20820 * Apply facets (pattern, enumeration).
20821 */
20822 ret = xmlSchemaValidateFacets(actxt, node, type,
20823 XML_SCHEMAS_UNKNOWN, value, val,
20824 len, fireErrors);
20825 if (ret != 0) {
20826 if (ret < 0) {
20827 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20828 "validating facets of list simple type");
20829 goto internal_error;
20830 }
20831 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20832 }
20833 }
20834 if (fireErrors && (ret > 0)) {
20835 /*
20836 * Report the normalized value.
20837 */
20838 normalize = 1;
20839 NORMALIZE(type);
20840 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20841 }
20842 } else if (VARIETY_UNION(type)) {
20843 xmlSchemaTypeLinkPtr memberLink;
20844 /*
20845 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20846 * not apply directly; however, the normalization behavior of ·union·
20847 * types is controlled by the value of whiteSpace on that one of the
20848 * ·memberTypes· against which the ·union· is successfully validated.
20849 *
20850 * This means that the value is normalized by the first validating
20851 * member type, then the facets of the union type are applied. This
20852 * needs changing of the value!
20853 */
20854
20855 /*
20856 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20857 * literal in the ·lexical space· of at least one member of
20858 * {member type definitions}
20859 */
20860 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20861 if (memberLink == NULL) {
20862 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20863 "union simple type has no member types");
20864 goto internal_error;
20865 }
20866 /*
20867 * Always normalize union type values, since we currently
20868 * cannot store the whitespace information with the value
20869 * itself; otherwise a later value-comparison would be
20870 * not possible.
20871 */
20872 while (memberLink != NULL) {
20873 if (valNeeded)
20874 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20875 memberLink->type, value, &val, 0, 1, 0);
20876 else
20877 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20878 memberLink->type, value, NULL, 0, 1, 0);
20879 if (ret <= 0)
20880 break;
20881 memberLink = memberLink->next;
20882 }
20883 if (ret != 0) {
20884 if (ret < 0) {
20885 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20886 "validating members of union simple type");
20887 goto internal_error;
20888 }
20889 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20890 }
20891 /*
20892 * Apply facets (pattern, enumeration).
20893 */
20894 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20895 /*
20896 * The normalization behavior of ·union· types is controlled by
20897 * the value of whiteSpace on that one of the ·memberTypes·
20898 * against which the ·union· is successfully validated.
20899 */
20900 NORMALIZE(memberLink->type);
20901 ret = xmlSchemaValidateFacets(actxt, node, type,
20902 XML_SCHEMAS_UNKNOWN, value, val,
20903 0, fireErrors);
20904 if (ret != 0) {
20905 if (ret < 0) {
20906 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20907 "validating facets of union simple type");
20908 goto internal_error;
20909 }
20910 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20911 }
20912 }
20913 if (fireErrors && (ret > 0))
20914 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20915 }
20916
20917 if (normValue != NULL)
20918 xmlFree(normValue);
20919 if (ret == 0) {
20920 if (retVal != NULL)
20921 *retVal = val;
20922 else if (val != NULL)
20923 xmlSchemaFreeValue(val);
20924 } else if (val != NULL)
20925 xmlSchemaFreeValue(val);
20926 return (ret);
20927internal_error:
20928 if (normValue != NULL)
20929 xmlFree(normValue);
20930 if (val != NULL)
20931 xmlSchemaFreeValue(val);
20932 return (-1);
20933}
20934
20935static int
20936xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20937 const xmlChar *value,
20938 const xmlChar **nsName,
20939 const xmlChar **localName)
20940{
20941 int ret = 0;
20942
20943 if ((nsName == NULL) || (localName == NULL))
20944 return (-1);
20945 *nsName = NULL;
20946 *localName = NULL;
20947
20948 ret = xmlValidateQName(value, 1);
20949 if (ret == -1)
20950 return (-1);
20951 if (ret > 0) {
20952 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20953 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20954 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20955 return (1);
20956 }
20957 {
20958 xmlChar *local = NULL;
20959 xmlChar *prefix;
20960
20961 /*
20962 * NOTE: xmlSplitQName2 will return a duplicated
20963 * string.
20964 */
20965 local = xmlSplitQName2(value, &prefix);
20966 VAL_CREATE_DICT;
20967 if (local == NULL)
20968 *localName = xmlDictLookup(vctxt->dict, value, -1);
20969 else {
20970 *localName = xmlDictLookup(vctxt->dict, local, -1);
20971 xmlFree(local);
20972 }
20973
20974 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20975
20976 if (prefix != NULL) {
20977 xmlFree(prefix);
20978 /*
20979 * A namespace must be found if the prefix is NOT NULL.
20980 */
20981 if (*nsName == NULL) {
20982 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20983 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20984 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20985 "The QName value '%s' has no "
20986 "corresponding namespace declaration in scope",
20987 value, NULL);
20988 return (2);
20989 }
20990 }
20991 }
20992 return (0);
20993}
20994
20995static int
20996xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20997 xmlSchemaAttrInfoPtr iattr,
20998 xmlSchemaTypePtr *localType,
20999 xmlSchemaElementPtr elemDecl)
21000{
21001 int ret = 0;
21002 /*
21003 * cvc-elt (3.3.4) : (4)
21004 * AND
21005 * Schema-Validity Assessment (Element) (cvc-assess-elt)
21006 * (1.2.1.2.1) - (1.2.1.2.4)
21007 * Handle 'xsi:type'.
21008 */
21009 if (localType == NULL)
21010 return (-1);
21011 *localType = NULL;
21012 if (iattr == NULL)
21013 return (0);
21014 else {
21015 const xmlChar *nsName = NULL, *local = NULL;
21016 /*
21017 * TODO: We should report a *warning* that the type was overriden
21018 * by the instance.
21019 */
21020 ACTIVATE_ATTRIBUTE(iattr);
21021 /*
21022 * (cvc-elt) (3.3.4) : (4.1)
21023 * (cvc-assess-elt) (1.2.1.2.2)
21024 */
21025 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
21026 &nsName, &local);
21027 if (ret != 0) {
21028 if (ret < 0) {
21029 VERROR_INT("xmlSchemaValidateElementByDeclaration",
21030 "calling xmlSchemaQNameExpand() to validate the "
21031 "attribute 'xsi:type'");
21032 goto internal_error;
21033 }
21034 goto exit;
21035 }
21036 /*
21037 * (cvc-elt) (3.3.4) : (4.2)
21038 * (cvc-assess-elt) (1.2.1.2.3)
21039 */
21040 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
21041 if (*localType == NULL) {
21042 xmlChar *str = NULL;
21043
21044 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21045 XML_SCHEMAV_CVC_ELT_4_2, NULL,
21046 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21047 "The QName value '%s' of the xsi:type attribute does not "
21048 "resolve to a type definition",
21049 xmlSchemaFormatQName(&str, nsName, local), NULL);
21050 FREE_AND_NULL(str);
21051 ret = vctxt->err;
21052 goto exit;
21053 }
21054 if (elemDecl != NULL) {
21055 int set = 0;
21056
21057 /*
21058 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
21059 * "The ·local type definition· must be validly
21060 * derived from the {type definition} given the union of
21061 * the {disallowed substitutions} and the {type definition}'s
21062 * {prohibited substitutions}, as defined in
21063 * Type Derivation OK (Complex) (§3.4.6)
21064 * (if it is a complex type definition),
21065 * or given {disallowed substitutions} as defined in Type
21066 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21067 * definition)."
21068 *
21069 * {disallowed substitutions}: the "block" on the element decl.
21070 * {prohibited substitutions}: the "block" on the type def.
21071 */
21072 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21073 (elemDecl->subtypes->flags &
21074 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21075 set |= SUBSET_EXTENSION;
21076
21077 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21078 (elemDecl->subtypes->flags &
21079 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21080 set |= SUBSET_RESTRICTION;
21081
21082 if (xmlSchemaCheckCOSDerivedOK(*localType,
21083 elemDecl->subtypes, set) != 0) {
21084 xmlChar *str = NULL;
21085
21086 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21087 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
21088 "The type definition '%s', specified by xsi:type, is "
21089 "blocked or not validly derived from the type definition "
21090 "of the element declaration",
21091 xmlSchemaFormatQName(&str,
21092 (*localType)->targetNamespace,
21093 (*localType)->name),
21094 NULL);
21095 FREE_AND_NULL(str);
21096 ret = vctxt->err;
21097 *localType = NULL;
21098 }
21099 }
21100 }
21101exit:
21102 ACTIVATE_ELEM;
21103 return (ret);
21104internal_error:
21105 ACTIVATE_ELEM;
21106 return (-1);
21107}
21108
21109static int
21110xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21111{
21112 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21113 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21114
21115 /*
21116 * cvc-elt (3.3.4) : 1
21117 */
21118 if (elemDecl == NULL) {
21119 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21120 "No matching declaration available");
21121 return (vctxt->err);
21122 }
21123 /*
21124 * cvc-elt (3.3.4) : 2
21125 */
21126 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21127 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21128 "The element declaration is abstract");
21129 return (vctxt->err);
21130 }
21131 if (actualType == NULL) {
21132 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21133 "The type definition is absent");
21134 return (XML_SCHEMAV_CVC_TYPE_1);
21135 }
21136 if (vctxt->nbAttrInfos != 0) {
21137 int ret;
21138 xmlSchemaAttrInfoPtr iattr;
21139 /*
21140 * cvc-elt (3.3.4) : 3
21141 * Handle 'xsi:nil'.
21142 */
21143 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21144 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21145 if (iattr) {
21146 ACTIVATE_ATTRIBUTE(iattr);
21147 /*
21148 * Validate the value.
21149 */
21150 ret = xmlSchemaVCheckCVCSimpleType(
21151 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21152 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21153 iattr->value, &(iattr->val), 1, 0, 0);
21154 ACTIVATE_ELEM;
21155 if (ret < 0) {
21156 VERROR_INT("xmlSchemaValidateElemDecl",
21157 "calling xmlSchemaVCheckCVCSimpleType() to "
21158 "validate the attribute 'xsi:nil'");
21159 return (-1);
21160 }
21161 if (ret == 0) {
21162 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21163 /*
21164 * cvc-elt (3.3.4) : 3.1
21165 */
21166 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21167 "The element is not 'nillable'");
21168 /* Does not return an error on purpose. */
21169 } else {
21170 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21171 /*
21172 * cvc-elt (3.3.4) : 3.2.2
21173 */
21174 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21175 (elemDecl->value != NULL)) {
21176 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21177 "The element cannot be 'nilled' because "
21178 "there is a fixed value constraint defined "
21179 "for it");
21180 /* Does not return an error on purpose. */
21181 } else
21182 vctxt->inode->flags |=
21183 XML_SCHEMA_ELEM_INFO_NILLED;
21184 }
21185 }
21186 }
21187 }
21188 /*
21189 * cvc-elt (3.3.4) : 4
21190 * Handle 'xsi:type'.
21191 */
21192 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21193 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21194 if (iattr) {
21195 xmlSchemaTypePtr localType = NULL;
21196
21197 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21198 elemDecl);
21199 if (ret != 0) {
21200 if (ret == -1) {
21201 VERROR_INT("xmlSchemaValidateElemDecl",
21202 "calling xmlSchemaProcessXSIType() to "
21203 "process the attribute 'xsi:type'");
21204 return (-1);
21205 }
21206 /* Does not return an error on purpose. */
21207 }
21208 if (localType != NULL) {
21209 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21210 actualType = localType;
21211 }
21212 }
21213 }
21214 /*
21215 * IDC: Register identity-constraint XPath matchers.
21216 */
21217 if ((elemDecl->idcs != NULL) &&
21218 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21219 return (-1);
21220 /*
21221 * No actual type definition.
21222 */
21223 if (actualType == NULL) {
21224 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21225 "The type definition is absent");
21226 return (XML_SCHEMAV_CVC_TYPE_1);
21227 }
21228 /*
21229 * Remember the actual type definition.
21230 */
21231 vctxt->inode->typeDef = actualType;
21232
21233 return (0);
21234}
21235
21236static int
21237xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21238{
21239 xmlSchemaAttrInfoPtr iattr;
21240 int ret = 0, i;
21241
21242 /*
21243 * SPEC cvc-type (3.1.1)
21244 * "The attributes of must be empty, excepting those whose namespace
21245 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21246 * whose local name is one of type, nil, schemaLocation or
21247 * noNamespaceSchemaLocation."
21248 */
21249 if (vctxt->nbAttrInfos == 0)
21250 return (0);
21251 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21252 iattr = vctxt->attrInfos[i];
21253 if (! iattr->metaType) {
21254 ACTIVATE_ATTRIBUTE(iattr)
21255 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21256 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21257 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21258 }
21259 }
21260 ACTIVATE_ELEM
21261 return (ret);
21262}
21263
21264/*
21265* Cleanup currently used attribute infos.
21266*/
21267static void
21268xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21269{
21270 int i;
21271 xmlSchemaAttrInfoPtr attr;
21272
21273 if (vctxt->nbAttrInfos == 0)
21274 return;
21275 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21276 attr = vctxt->attrInfos[i];
21277 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21278 if (attr->localName != NULL)
21279 xmlFree((xmlChar *) attr->localName);
21280 if (attr->nsName != NULL)
21281 xmlFree((xmlChar *) attr->nsName);
21282 }
21283 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21284 if (attr->value != NULL)
21285 xmlFree((xmlChar *) attr->value);
21286 }
21287 if (attr->val != NULL) {
21288 xmlSchemaFreeValue(attr->val);
21289 attr->val = NULL;
21290 }
21291 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21292 }
21293 vctxt->nbAttrInfos = 0;
21294}
21295
21296/*
21297* 3.4.4 Complex Type Definition Validation Rules
21298* Element Locally Valid (Complex Type) (cvc-complex-type)
21299* 3.2.4 Attribute Declaration Validation Rules
21300* Validation Rule: Attribute Locally Valid (cvc-attribute)
21301* Attribute Locally Valid (Use) (cvc-au)
21302*
21303* Only "assessed" attribute information items will be visible to
21304* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21305*/
21306static int
21307xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21308{
21309 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21310 xmlSchemaAttributeLinkPtr attrUseLink;
21311 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21312 xmlSchemaAttrInfoPtr attr, tmpAttr;
21313 int i, found, nbAttrs;
21314 int xpathRes = 0, res, wildIDs = 0, fixed;
21315
21316 /*
21317 * SPEC (cvc-attribute)
21318 * (1) "The declaration must not be ·absent· (see Missing
21319 * Sub-components (§5.3) for how this can fail to be
21320 * the case)."
21321 * (2) "Its {type definition} must not be absent."
21322 *
21323 * NOTE (1) + (2): This is not handled here, since we currently do not
21324 * allow validation against schemas which have missing sub-components.
21325 *
21326 * SPEC (cvc-complex-type)
21327 * (3) "For each attribute information item in the element information
21328 * item's [attributes] excepting those whose [namespace name] is
21329 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21330 * [local name] is one of type, nil, schemaLocation or
21331 * noNamespaceSchemaLocation, the appropriate case among the following
21332 * must be true:
21333 *
21334 */
21335 nbAttrs = vctxt->nbAttrInfos;
21336 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21337 attrUseLink = attrUseLink->next) {
21338
21339 found = 0;
21340 attrUse = attrUseLink->attr;
21341 /*
21342 * VAL TODO: Implement a real "attribute use" component.
21343 */
21344 if (attrUse->refDecl != NULL)
21345 attrDecl = attrUse->refDecl;
21346 else
21347 attrDecl = attrUse;
21348 for (i = 0; i < nbAttrs; i++) {
21349 attr = vctxt->attrInfos[i];
21350 /*
21351 * SPEC (cvc-complex-type) (3)
21352 * Skip meta attributes.
21353 */
21354 if (attr->metaType)
21355 continue;
21356 if (attr->localName[0] != attrDecl->name[0])
21357 continue;
21358 if (!xmlStrEqual(attr->localName, attrDecl->name))
21359 continue;
21360 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21361 continue;
21362 found = 1;
21363 /*
21364 * SPEC (cvc-complex-type)
21365 * (3.1) "If there is among the {attribute uses} an attribute
21366 * use with an {attribute declaration} whose {name} matches
21367 * the attribute information item's [local name] and whose
21368 * {target namespace} is identical to the attribute information
21369 * item's [namespace name] (where an ·absent· {target namespace}
21370 * is taken to be identical to a [namespace name] with no value),
21371 * then the attribute information must be ·valid· with respect
21372 * to that attribute use as per Attribute Locally Valid (Use)
21373 * (§3.5.4). In this case the {attribute declaration} of that
21374 * attribute use is the ·context-determined declaration· for the
21375 * attribute information item with respect to Schema-Validity
21376 * Assessment (Attribute) (§3.2.4) and
21377 * Assessment Outcome (Attribute) (§3.2.5).
21378 */
21379 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21380 attr->use = attrUse;
21381 /*
21382 * Context-determined declaration.
21383 */
21384 attr->decl = attrDecl;
21385 attr->typeDef = attrDecl->subtypes;
21386 break;
21387 }
21388
21389 if (found)
21390 continue;
21391
21392 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21393 /*
21394 * Handle non-existent, required attributes.
21395 *
21396 * SPEC (cvc-complex-type)
21397 * (4) "The {attribute declaration} of each attribute use in
21398 * the {attribute uses} whose {required} is true matches one
21399 * of the attribute information items in the element information
21400 * item's [attributes] as per clause 3.1 above."
21401 */
21402 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21403 if (tmpAttr == NULL) {
21404 VERROR_INT(
21405 "xmlSchemaVAttributesComplex",
21406 "calling xmlSchemaGetFreshAttrInfo()");
21407 return (-1);
21408 }
21409 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21410 tmpAttr->use = attrUse;
21411 tmpAttr->decl = attrDecl;
21412 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21413 ((attrUse->defValue != NULL) ||
21414 (attrDecl->defValue != NULL))) {
21415 /*
21416 * Handle non-existent, optional, default/fixed attributes.
21417 */
21418 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21419 if (tmpAttr == NULL) {
21420 VERROR_INT(
21421 "xmlSchemaVAttributesComplex",
21422 "calling xmlSchemaGetFreshAttrInfo()");
21423 return (-1);
21424 }
21425 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21426 tmpAttr->use = attrUse;
21427 tmpAttr->decl = attrDecl;
21428 tmpAttr->typeDef = attrDecl->subtypes;
21429 tmpAttr->localName = attrDecl->name;
21430 tmpAttr->nsName = attrDecl->targetNamespace;
21431 }
21432 }
21433 if (vctxt->nbAttrInfos == 0)
21434 return (0);
21435 /*
21436 * Validate against the wildcard.
21437 */
21438 if (type->attributeWildcard != NULL) {
21439 /*
21440 * SPEC (cvc-complex-type)
21441 * (3.2.1) "There must be an {attribute wildcard}."
21442 */
21443 for (i = 0; i < nbAttrs; i++) {
21444 attr = vctxt->attrInfos[i];
21445 /*
21446 * SPEC (cvc-complex-type) (3)
21447 * Skip meta attributes.
21448 */
21449 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21450 continue;
21451 /*
21452 * SPEC (cvc-complex-type)
21453 * (3.2.2) "The attribute information item must be ·valid· with
21454 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21455 *
21456 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21457 * "... its [namespace name] must be ·valid· with respect to
21458 * the wildcard constraint, as defined in Wildcard allows
21459 * Namespace Name (§3.10.4)."
21460 */
21461 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21462 attr->nsName)) {
21463 /*
21464 * Handle processContents.
21465 *
21466 * SPEC (cvc-wildcard):
21467 * processContents | context-determined declaration:
21468 * "strict" "mustFind"
21469 * "lax" "none"
21470 * "skip" "skip"
21471 */
21472 if (type->attributeWildcard->processContents ==
21473 XML_SCHEMAS_ANY_SKIP) {
21474 /*
21475 * context-determined declaration = "skip"
21476 *
21477 * SPEC PSVI Assessment Outcome (Attribute)
21478 * [validity] = "notKnown"
21479 * [validation attempted] = "none"
21480 */
21481 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21482 continue;
21483 }
21484 /*
21485 * Find an attribute declaration.
21486 */
21487 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21488 attr->localName, attr->nsName);
21489 if (attr->decl != NULL) {
21490 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21491 /*
21492 * SPEC (cvc-complex-type)
21493 * (5) "Let [Definition:] the wild IDs be the set of
21494 * all attribute information item to which clause 3.2
21495 * applied and whose ·validation· resulted in a
21496 * ·context-determined declaration· of mustFind or no
21497 * ·context-determined declaration· at all, and whose
21498 * [local name] and [namespace name] resolve (as
21499 * defined by QName resolution (Instance) (§3.15.4)) to
21500 * an attribute declaration whose {type definition} is
21501 * or is derived from ID. Then all of the following
21502 * must be true:"
21503 */
21504 attr->typeDef = attr->decl->subtypes;
21505 if (xmlSchemaIsDerivedFromBuiltInType(
21506 attr->typeDef, XML_SCHEMAS_ID)) {
21507 /*
21508 * SPEC (5.1) "There must be no more than one
21509 * item in ·wild IDs·."
21510 */
21511 if (wildIDs != 0) {
21512 /* VAL TODO */
21513 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21514 TODO
21515 continue;
21516 }
21517 wildIDs++;
21518 /*
21519 * SPEC (cvc-complex-type)
21520 * (5.2) "If ·wild IDs· is non-empty, there must not
21521 * be any attribute uses among the {attribute uses}
21522 * whose {attribute declaration}'s {type definition}
21523 * is or is derived from ID."
21524 */
21525 for (attrUseLink = type->attributeUses;
21526 attrUseLink != NULL;
21527 attrUseLink = attrUseLink->next) {
21528 if (xmlSchemaIsDerivedFromBuiltInType(
21529 attrUseLink->attr->subtypes,
21530 XML_SCHEMAS_ID)) {
21531 /* VAL TODO */
21532 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21533 TODO
21534 }
21535 }
21536 }
21537 } else if (type->attributeWildcard->processContents ==
21538 XML_SCHEMAS_ANY_LAX) {
21539 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21540 /*
21541 * SPEC PSVI Assessment Outcome (Attribute)
21542 * [validity] = "notKnown"
21543 * [validation attempted] = "none"
21544 */
21545 } else {
21546 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21547 }
21548 }
21549 }
21550 }
21551
21552
21553 if (vctxt->nbAttrInfos == 0)
21554 return (0);
21555
21556 /*
21557 * Validate values, create default attributes, evaluate IDCs.
21558 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021559 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21560 attr = vctxt->attrInfos[i];
21561 /*
21562 * VAL TODO: Note that we won't try to resolve IDCs to
21563 * "lax" and "skip" validated attributes. Check what to
21564 * do in this case.
21565 */
21566 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21567 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21568 continue;
21569 /*
21570 * VAL TODO: What to do if the type definition is missing?
21571 */
21572 if (attr->typeDef == NULL) {
21573 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21574 continue;
21575 }
21576
21577 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021578 fixed = 0;
21579 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021580
21581 if (vctxt->xpathStates != NULL) {
21582 /*
21583 * Evaluate IDCs.
21584 */
21585 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21586 XML_ATTRIBUTE_NODE);
21587 if (xpathRes == -1) {
21588 VERROR_INT("xmlSchemaVAttributesComplex",
21589 "calling xmlSchemaXPathEvaluate()");
21590 goto internal_error;
21591 }
21592 }
21593
21594 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21595 /*
21596 * Default/fixed attributes.
21597 */
21598 if (xpathRes) {
21599 if (attr->use->defValue == NULL) {
21600 attr->value = (xmlChar *) attr->use->defValue;
21601 attr->val = attr->use->defVal;
21602 } else {
21603 attr->value = (xmlChar *) attr->decl->defValue;
21604 attr->val = attr->decl->defVal;
21605 }
21606 /*
21607 * IDCs will consume the precomputed default value,
21608 * so we need to clone it.
21609 */
21610 if (attr->val == NULL) {
21611 VERROR_INT("xmlSchemaVAttributesComplex",
21612 "default/fixed value on an attribute use was "
21613 "not precomputed");
21614 goto internal_error;
21615 }
21616 attr->val = xmlSchemaCopyValue(attr->val);
21617 if (attr->val == NULL) {
21618 VERROR_INT("xmlSchemaVAttributesComplex",
21619 "calling xmlSchemaCopyValue()");
21620 goto internal_error;
21621 }
21622 }
21623 /*
21624 * PSVI: Add the default attribute to the current element.
21625 * VAL TODO: Should we use the *normalized* value? This currently
21626 * uses the *initial* value.
21627 */
21628 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21629 (attr->node != NULL) && (attr->node->doc != NULL)) {
21630 xmlChar *normValue;
21631 const xmlChar *value;
21632
21633 value = attr->value;
21634 /*
21635 * Normalize the value.
21636 */
21637 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21638 attr->value);
21639 if (normValue != NULL)
21640 value = BAD_CAST normValue;
21641
21642 if (attr->nsName == NULL) {
21643 if (xmlNewProp(attr->node->parent,
21644 attr->localName, value) == NULL) {
21645 VERROR_INT("xmlSchemaVAttributesComplex",
21646 "callling xmlNewProp()");
21647 if (normValue != NULL)
21648 xmlFree(normValue);
21649 goto internal_error;
21650 }
21651 } else {
21652 xmlNsPtr ns;
21653
21654 ns = xmlSearchNsByHref(attr->node->doc,
21655 attr->node->parent, attr->nsName);
21656 if (ns == NULL) {
21657 xmlChar prefix[12];
21658 int counter = 0;
21659
21660 /*
21661 * Create a namespace declaration on the validation
21662 * root node if no namespace declaration is in scope.
21663 */
21664 do {
21665 snprintf((char *) prefix, 12, "p%d", counter++);
21666 ns = xmlSearchNs(attr->node->doc,
21667 attr->node->parent, BAD_CAST prefix);
21668 if (counter > 1000) {
21669 VERROR_INT(
21670 "xmlSchemaVAttributesComplex",
21671 "could not compute a ns prefix for a "
21672 "default/fixed attribute");
21673 if (normValue != NULL)
21674 xmlFree(normValue);
21675 goto internal_error;
21676 }
21677 } while (ns != NULL);
21678 ns = xmlNewNs(vctxt->validationRoot,
21679 attr->nsName, BAD_CAST prefix);
21680 }
21681 xmlNewNsProp(attr->node->parent, ns,
21682 attr->localName, value);
21683 }
21684 if (normValue != NULL)
21685 xmlFree(normValue);
21686 }
21687 /*
21688 * Go directly to IDC evaluation.
21689 */
21690 goto eval_idcs;
21691 }
21692 /*
21693 * Validate the value.
21694 */
21695 if (vctxt->value != NULL) {
21696 /*
21697 * Free last computed value; just for safety reasons.
21698 */
21699 xmlSchemaFreeValue(vctxt->value);
21700 vctxt->value = NULL;
21701 }
21702 /*
21703 * Note that the attribute *use* can be unavailable, if
21704 * the attribute was a wild attribute.
21705 */
21706 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21707 ((attr->use != NULL) &&
21708 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21709 fixed = 1;
21710 else
21711 fixed = 0;
21712 /*
21713 * SPEC (cvc-attribute)
21714 * (3) "The item's ·normalized value· must be locally ·valid·
21715 * with respect to that {type definition} as per
21716 * String Valid (§3.14.4)."
21717 *
21718 * VAL TODO: Do we already have the
21719 * "normalized attribute value" here?
21720 */
21721 if (xpathRes || fixed) {
21722 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21723 /*
21724 * Request a computed value.
21725 */
21726 res = xmlSchemaVCheckCVCSimpleType(
21727 (xmlSchemaAbstractCtxtPtr) vctxt,
21728 attr->node, attr->typeDef, attr->value, &(attr->val),
21729 1, 1, 0);
21730 } else {
21731 res = xmlSchemaVCheckCVCSimpleType(
21732 (xmlSchemaAbstractCtxtPtr) vctxt,
21733 attr->node, attr->typeDef, attr->value, NULL,
21734 1, 0, 0);
21735 }
21736
21737 if (res != 0) {
21738 if (res == -1) {
21739 VERROR_INT("xmlSchemaVAttributesComplex",
21740 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21741 goto internal_error;
21742 }
21743 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21744 /*
21745 * SPEC PSVI Assessment Outcome (Attribute)
21746 * [validity] = "invalid"
21747 */
21748 goto eval_idcs;
21749 }
21750
21751 if (fixed) {
21752 int ws;
21753 /*
21754 * SPEC Attribute Locally Valid (Use) (cvc-au)
21755 * "For an attribute information item to be·valid·
21756 * with respect to an attribute use its *normalized*
21757 * value· must match the *canonical* lexical
21758 * representation of the attribute use's {value
21759 * constraint}value, if it is present and fixed."
21760 *
21761 * VAL TODO: The requirement for the *canonical* value
21762 * will be removed in XML Schema 1.1.
21763 */
21764 /*
21765 * SPEC Attribute Locally Valid (cvc-attribute)
21766 * (4) "The item's *actual* value· must match the *value* of
21767 * the {value constraint}, if it is present and fixed."
21768 */
21769 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21770 if (attr->val == NULL) {
21771 /* VAL TODO: A value was not precomputed. */
21772 TODO
21773 goto eval_idcs;
21774 }
21775 if ((attr->use != NULL) &&
21776 (attr->use->defValue != NULL)) {
21777 if (attr->use->defVal == NULL) {
21778 /* VAL TODO: A default value was not precomputed. */
21779 TODO
21780 goto eval_idcs;
21781 }
21782 attr->vcValue = attr->use->defValue;
21783 /*
21784 if (xmlSchemaCompareValuesWhtsp(attr->val,
21785 (xmlSchemaWhitespaceValueType) ws,
21786 attr->use->defVal,
21787 (xmlSchemaWhitespaceValueType) ws) != 0) {
21788 */
21789 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21790 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21791 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021792 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021793 /* VAL TODO: A default value was not precomputed. */
21794 TODO
21795 goto eval_idcs;
21796 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021797 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021798 /*
21799 if (xmlSchemaCompareValuesWhtsp(attr->val,
21800 (xmlSchemaWhitespaceValueType) ws,
21801 attrDecl->defVal,
21802 (xmlSchemaWhitespaceValueType) ws) != 0) {
21803 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021804 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021805 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21806 }
21807 /*
21808 * [validity] = "valid"
21809 */
21810 }
21811eval_idcs:
21812 /*
21813 * Evaluate IDCs.
21814 */
21815 if (xpathRes) {
21816 if (xmlSchemaXPathProcessHistory(vctxt,
21817 vctxt->depth +1) == -1) {
21818 VERROR_INT("xmlSchemaVAttributesComplex",
21819 "calling xmlSchemaXPathEvaluate()");
21820 goto internal_error;
21821 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000021822 } else if (vctxt->xpathStates != NULL)
21823 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021824 }
21825
21826 /*
21827 * Report errors.
21828 */
21829 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21830 attr = vctxt->attrInfos[i];
21831 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21832 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21833 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21834 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21835 continue;
21836 ACTIVATE_ATTRIBUTE(attr);
21837 switch (attr->state) {
21838 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21839 xmlChar *str = NULL;
21840 ACTIVATE_ELEM;
21841 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21842 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21843 "The attribute '%s' is required but missing",
21844 xmlSchemaFormatQName(&str,
21845 attr->decl->targetNamespace,
21846 attr->decl->name),
21847 NULL);
21848 FREE_AND_NULL(str)
21849 break;
21850 }
21851 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21852 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21853 "The type definition is absent");
21854 break;
21855 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21856 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21857 XML_SCHEMAV_CVC_AU, NULL, NULL,
21858 "The value '%s' does not match the fixed "
21859 "value constraint '%s'",
21860 attr->value, attr->vcValue);
21861 break;
21862 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21863 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21864 "No matching global attribute declaration available, but "
21865 "demanded by the strict wildcard");
21866 break;
21867 case XML_SCHEMAS_ATTR_UNKNOWN:
21868 if (attr->metaType)
21869 break;
21870 /*
21871 * MAYBE VAL TODO: One might report different error messages
21872 * for the following errors.
21873 */
21874 if (type->attributeWildcard == NULL) {
21875 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21876 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21877 } else {
21878 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21879 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21880 }
21881 break;
21882 default:
21883 break;
21884 }
21885 }
21886
21887 ACTIVATE_ELEM;
21888 return (0);
21889internal_error:
21890 ACTIVATE_ELEM;
21891 return (-1);
21892}
21893
21894static int
21895xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21896 int *skip)
21897{
21898 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21899 /*
21900 * The namespace of the element was already identified to be
21901 * matching the wildcard.
21902 */
21903 if ((skip == NULL) || (wild == NULL) ||
21904 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21905 VERROR_INT("xmlSchemaValidateElemWildcard",
21906 "bad arguments");
21907 return (-1);
21908 }
21909 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021910 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21911 /*
21912 * URGENT VAL TODO: Either we need to position the stream to the
21913 * next sibling, or walk the whole subtree.
21914 */
21915 *skip = 1;
21916 return (0);
21917 }
21918 {
21919 xmlSchemaElementPtr decl = NULL;
21920
21921 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21922 vctxt->inode->localName, vctxt->inode->nsName,
21923 NULL);
21924 if (decl != NULL) {
21925 vctxt->inode->decl = decl;
21926 return (0);
21927 }
21928 }
21929 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21930 /* VAL TODO: Change to proper error code. */
21931 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21932 "No matching global element declaration available, but "
21933 "demanded by the strict wildcard");
21934 return (vctxt->err);
21935 }
21936 if (vctxt->nbAttrInfos != 0) {
21937 xmlSchemaAttrInfoPtr iattr;
21938 /*
21939 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21940 * (1.2.1.2.1) - (1.2.1.2.3 )
21941 *
21942 * Use the xsi:type attribute for the type definition.
21943 */
21944 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21945 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21946 if (iattr != NULL) {
21947 if (xmlSchemaProcessXSIType(vctxt, iattr,
21948 &(vctxt->inode->typeDef), NULL) == -1) {
21949 VERROR_INT("xmlSchemaValidateElemWildcard",
21950 "calling xmlSchemaProcessXSIType() to "
21951 "process the attribute 'xsi:nil'");
21952 return (-1);
21953 }
21954 /*
21955 * Don't return an error on purpose.
21956 */
21957 return (0);
21958 }
21959 }
21960 /*
21961 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21962 *
21963 * Fallback to "anyType".
21964 */
21965 vctxt->inode->typeDef =
21966 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21967 return (0);
21968}
21969
21970/*
21971* xmlSchemaCheckCOSValidDefault:
21972*
21973* This will be called if: not nilled, no content and a default/fixed
21974* value is provided.
21975*/
21976
21977static int
21978xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21979 const xmlChar *value,
21980 xmlSchemaValPtr *val)
21981{
21982 int ret = 0;
21983 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21984
21985 /*
21986 * cos-valid-default:
21987 * Schema Component Constraint: Element Default Valid (Immediate)
21988 * For a string to be a valid default with respect to a type
21989 * definition the appropriate case among the following must be true:
21990 */
21991 if IS_COMPLEX_TYPE(inode->typeDef) {
21992 /*
21993 * Complex type.
21994 *
21995 * SPEC (2.1) "its {content type} must be a simple type definition
21996 * or mixed."
21997 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21998 * type}'s particle must be ·emptiable· as defined by
21999 * Particle Emptiable (§3.9.6)."
22000 */
22001 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
22002 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
22003 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
22004 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
22005 /* NOTE that this covers (2.2.2) as well. */
22006 VERROR(ret, NULL,
22007 "For a string to be a valid default, the type definition "
22008 "must be a simple type or a complex type with simple content "
22009 "or mixed content and a particle emptiable");
22010 return(ret);
22011 }
22012 }
22013 /*
22014 * 1 If the type definition is a simple type definition, then the string
22015 * must be ·valid· with respect to that definition as defined by String
22016 * Valid (§3.14.4).
22017 *
22018 * AND
22019 *
22020 * 2.2.1 If the {content type} is a simple type definition, then the
22021 * string must be ·valid· with respect to that simple type definition
22022 * as defined by String Valid (§3.14.4).
22023 */
22024 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22025
22026 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22027 NULL, inode->typeDef, value, val, 1, 1, 0);
22028
22029 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22030
22031 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22032 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
22033 }
22034 if (ret < 0) {
22035 VERROR_INT("xmlSchemaCheckCOSValidDefault",
22036 "calling xmlSchemaVCheckCVCSimpleType()");
22037 }
22038 return (ret);
22039}
22040
22041static void
22042xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22043 const xmlChar * name ATTRIBUTE_UNUSED,
22044 xmlSchemaElementPtr item,
22045 xmlSchemaNodeInfoPtr inode)
22046{
22047 inode->decl = item;
22048#ifdef DEBUG_CONTENT
22049 {
22050 xmlChar *str = NULL;
22051
22052 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
22053 xmlGenericError(xmlGenericErrorContext,
22054 "AUTOMATON callback for '%s' [declaration]\n",
22055 xmlSchemaFormatQName(&str,
22056 inode->localName, inode->nsName));
22057 } else {
22058 xmlGenericError(xmlGenericErrorContext,
22059 "AUTOMATON callback for '%s' [wildcard]\n",
22060 xmlSchemaFormatQName(&str,
22061 inode->localName, inode->nsName));
22062
22063 }
22064 FREE_AND_NULL(str)
22065 }
22066#endif
22067}
22068
22069static int
22070xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022071{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022072 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22073 if (vctxt->inode == NULL) {
22074 VERROR_INT("xmlSchemaValidatorPushElem",
22075 "calling xmlSchemaGetFreshElemInfo()");
22076 return (-1);
22077 }
22078 vctxt->nbAttrInfos = 0;
22079 return (0);
22080}
22081
22082static int
22083xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22084 xmlSchemaNodeInfoPtr inode,
22085 xmlSchemaTypePtr type,
22086 const xmlChar *value)
22087{
22088 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22089 return (xmlSchemaVCheckCVCSimpleType(
22090 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22091 type, value, &(inode->val), 1, 1, 0));
22092 else
22093 return (xmlSchemaVCheckCVCSimpleType(
22094 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22095 type, value, NULL, 1, 0, 0));
22096}
22097
22098
22099
22100/*
22101* Process END of element.
22102*/
22103static int
22104xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22105{
22106 int ret = 0;
22107 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22108
22109 if (vctxt->nbAttrInfos != 0)
22110 xmlSchemaClearAttrInfos(vctxt);
22111 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22112 /*
22113 * This element was not expected;
22114 * we will not validate child elements of broken parents.
22115 * Skip validation of all content of the parent.
22116 */
22117 vctxt->skipDepth = vctxt->depth -1;
22118 goto end_elem;
22119 }
22120 if ((inode->typeDef == NULL) ||
22121 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22122 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022123 * 1. the type definition might be missing if the element was
22124 * error prone
22125 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022126 */
22127 goto end_elem;
22128 }
22129 /*
22130 * Check the content model.
22131 */
22132 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22133 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22134
22135 /*
22136 * Workaround for "anyType".
22137 */
22138 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22139 goto character_content;
22140
22141 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22142 xmlChar *values[10];
22143 int terminal, nbval = 10, nbneg;
22144
22145 if (inode->regexCtxt == NULL) {
22146 /*
22147 * Create the regex context.
22148 */
22149 inode->regexCtxt =
22150 xmlRegNewExecCtxt(inode->typeDef->contModel,
22151 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22152 vctxt);
22153 if (inode->regexCtxt == NULL) {
22154 VERROR_INT("xmlSchemaValidatorPopElem",
22155 "failed to create a regex context");
22156 goto internal_error;
22157 }
22158#ifdef DEBUG_AUTOMATA
22159 xmlGenericError(xmlGenericErrorContext,
22160 "AUTOMATON create on '%s'\n", inode->localName);
22161#endif
22162 }
22163 /*
22164 * Get hold of the still expected content, since a further
22165 * call to xmlRegExecPushString() will loose this information.
22166 */
22167 xmlRegExecNextValues(inode->regexCtxt,
22168 &nbval, &nbneg, &values[0], &terminal);
22169 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22170 if (ret <= 0) {
22171 /*
22172 * Still missing something.
22173 */
22174 ret = 1;
22175 inode->flags |=
22176 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22177 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22178 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22179 "Missing child element(s)",
22180 nbval, nbneg, values);
22181#ifdef DEBUG_AUTOMATA
22182 xmlGenericError(xmlGenericErrorContext,
22183 "AUTOMATON missing ERROR on '%s'\n",
22184 inode->localName);
22185#endif
22186 } else {
22187 /*
22188 * Content model is satisfied.
22189 */
22190 ret = 0;
22191#ifdef DEBUG_AUTOMATA
22192 xmlGenericError(xmlGenericErrorContext,
22193 "AUTOMATON succeeded on '%s'\n",
22194 inode->localName);
22195#endif
22196 }
22197
22198 }
22199 }
22200 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22201 goto end_elem;
22202
22203character_content:
22204
22205 if (vctxt->value != NULL) {
22206 xmlSchemaFreeValue(vctxt->value);
22207 vctxt->value = NULL;
22208 }
22209 /*
22210 * Check character content.
22211 */
22212 if (inode->decl == NULL) {
22213 /*
22214 * Speedup if no declaration exists.
22215 */
22216 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22217 ret = xmlSchemaVCheckINodeDataType(vctxt,
22218 inode, inode->typeDef, inode->value);
22219 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22220 ret = xmlSchemaVCheckINodeDataType(vctxt,
22221 inode, inode->typeDef->contentTypeDef,
22222 inode->value);
22223 }
22224 if (ret < 0) {
22225 VERROR_INT("xmlSchemaValidatorPopElem",
22226 "calling xmlSchemaVCheckCVCSimpleType()");
22227 goto internal_error;
22228 }
22229 goto end_elem;
22230 }
22231 /*
22232 * cvc-elt (3.3.4) : 5
22233 * The appropriate case among the following must be true:
22234 */
22235 /*
22236 * cvc-elt (3.3.4) : 5.1
22237 * If the declaration has a {value constraint},
22238 * the item has neither element nor character [children] and
22239 * clause 3.2 has not applied, then all of the following must be true:
22240 */
22241 if ((inode->decl->value != NULL) &&
22242 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22243 (! INODE_NILLED(inode))) {
22244 /*
22245 * cvc-elt (3.3.4) : 5.1.1
22246 * If the ·actual type definition· is a ·local type definition·
22247 * then the canonical lexical representation of the {value constraint}
22248 * value must be a valid default for the ·actual type definition· as
22249 * defined in Element Default Valid (Immediate) (§3.3.6).
22250 */
22251 /*
22252 * NOTE: 'local' above means types aquired by xsi:type.
22253 * NOTE: Although the *canonical* value is stated, it is not
22254 * relevant if canonical or not. Additionally XML Schema 1.1
22255 * will removed this requirement as well.
22256 */
22257 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22258
22259 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22260 inode->decl->value, &(inode->val));
22261 if (ret != 0) {
22262 if (ret < 0) {
22263 VERROR_INT("xmlSchemaValidatorPopElem",
22264 "calling xmlSchemaCheckCOSValidDefault()");
22265 goto internal_error;
22266 }
22267 goto end_elem;
22268 }
22269 /*
22270 * Stop here, to avoid redundant validation of the value
22271 * (see following).
22272 */
22273 goto default_psvi;
22274 }
22275 /*
22276 * cvc-elt (3.3.4) : 5.1.2
22277 * The element information item with the canonical lexical
22278 * representation of the {value constraint} value used as its
22279 * ·normalized value· must be ·valid· with respect to the
22280 * ·actual type definition· as defined by Element Locally Valid (Type)
22281 * (§3.3.4).
22282 */
22283 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22284 ret = xmlSchemaVCheckINodeDataType(vctxt,
22285 inode, inode->typeDef, inode->decl->value);
22286 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22287 ret = xmlSchemaVCheckINodeDataType(vctxt,
22288 inode, inode->typeDef->contentTypeDef,
22289 inode->decl->value);
22290 }
22291 if (ret != 0) {
22292 if (ret < 0) {
22293 VERROR_INT("xmlSchemaValidatorPopElem",
22294 "calling xmlSchemaVCheckCVCSimpleType()");
22295 goto internal_error;
22296 }
22297 goto end_elem;
22298 }
22299
22300default_psvi:
22301 /*
22302 * PSVI: Create a text node on the instance element.
22303 */
22304 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22305 (inode->node != NULL)) {
22306 xmlNodePtr textChild;
22307 xmlChar *normValue;
22308 /*
22309 * VAL TODO: Normalize the value.
22310 */
22311 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22312 inode->decl->value);
22313 if (normValue != NULL) {
22314 textChild = xmlNewText(BAD_CAST normValue);
22315 xmlFree(normValue);
22316 } else
22317 textChild = xmlNewText(inode->decl->value);
22318 if (textChild == NULL) {
22319 VERROR_INT("xmlSchemaValidatorPopElem",
22320 "calling xmlNewText()");
22321 goto internal_error;
22322 } else
22323 xmlAddChild(inode->node, textChild);
22324 }
22325
22326 } else if (! INODE_NILLED(inode)) {
22327 /*
22328 * 5.2.1 The element information item must be ·valid· with respect
22329 * to the ·actual type definition· as defined by Element Locally
22330 * Valid (Type) (§3.3.4).
22331 */
22332 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22333 /*
22334 * SPEC (cvc-type) (3.1)
22335 * "If the type definition is a simple type definition, ..."
22336 * (3.1.3) "If clause 3.2 of Element Locally Valid
22337 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22338 * must be ·valid· with respect to the type definition as defined
22339 * by String Valid (§3.14.4).
22340 */
22341 ret = xmlSchemaVCheckINodeDataType(vctxt,
22342 inode, inode->typeDef, inode->value);
22343 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22344 /*
22345 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22346 * definition, then the element information item must be
22347 * ·valid· with respect to the type definition as per
22348 * Element Locally Valid (Complex Type) (§3.4.4);"
22349 *
22350 * SPEC (cvc-complex-type) (2.2)
22351 * "If the {content type} is a simple type definition, ...
22352 * the ·normalized value· of the element information item is
22353 * ·valid· with respect to that simple type definition as
22354 * defined by String Valid (§3.14.4)."
22355 */
22356 ret = xmlSchemaVCheckINodeDataType(vctxt,
22357 inode, inode->typeDef->contentTypeDef, inode->value);
22358 }
22359 if (ret != 0) {
22360 if (ret < 0) {
22361 VERROR_INT("xmlSchemaValidatorPopElem",
22362 "calling xmlSchemaVCheckCVCSimpleType()");
22363 goto internal_error;
22364 }
22365 goto end_elem;
22366 }
22367 /*
22368 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22369 * not applied, all of the following must be true:
22370 */
22371 if ((inode->decl->value != NULL) &&
22372 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22373
22374 /*
22375 * TODO: We will need a computed value, when comparison is
22376 * done on computed values.
22377 */
22378 /*
22379 * 5.2.2.1 The element information item must have no element
22380 * information item [children].
22381 */
22382 if (inode->flags &
22383 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22384 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22385 VERROR(ret, NULL,
22386 "The content must not containt element nodes since "
22387 "there is a fixed value constraint");
22388 goto end_elem;
22389 } else {
22390 /*
22391 * 5.2.2.2 The appropriate case among the following must
22392 * be true:
22393 */
22394 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22395 /*
22396 * 5.2.2.2.1 If the {content type} of the ·actual type
22397 * definition· is mixed, then the *initial value* of the
22398 * item must match the canonical lexical representation
22399 * of the {value constraint} value.
22400 *
22401 * ... the *initial value* of an element information
22402 * item is the string composed of, in order, the
22403 * [character code] of each character information item in
22404 * the [children] of that element information item.
22405 */
22406 if (! xmlStrEqual(inode->value, inode->decl->value)){
22407 /*
22408 * VAL TODO: Report invalid & expected values as well.
22409 * VAL TODO: Implement the canonical stuff.
22410 */
22411 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22412 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22413 ret, NULL, NULL,
22414 "The initial value '%s' does not match the fixed "
22415 "value constraint '%s'",
22416 inode->value, inode->decl->value);
22417 goto end_elem;
22418 }
22419 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22420 /*
22421 * 5.2.2.2.2 If the {content type} of the ·actual type
22422 * definition· is a simple type definition, then the
22423 * *actual value* of the item must match the canonical
22424 * lexical representation of the {value constraint} value.
22425 */
22426 /*
22427 * VAL TODO: *actual value* is the normalized value, impl.
22428 * this.
22429 * VAL TODO: Report invalid & expected values as well.
22430 * VAL TODO: Implement a comparison with the computed values.
22431 */
22432 if (! xmlStrEqual(inode->value,
22433 inode->decl->value)) {
22434 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22435 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22436 ret, NULL, NULL,
22437 "The actual value '%s' does not match the fixed "
22438 "value constraint '%s'",
22439 inode->value,
22440 inode->decl->value);
22441 goto end_elem;
22442 }
22443 }
22444 }
22445 }
22446 }
22447
22448end_elem:
22449 if (vctxt->depth < 0) {
22450 /* TODO: raise error? */
22451 return (0);
22452 }
22453 if (vctxt->depth == vctxt->skipDepth)
22454 vctxt->skipDepth = -1;
22455 /*
22456 * Evaluate the history of XPath state objects.
22457 */
22458 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22459 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022460 /*
22461 * TODO: 6 The element information item must be ·valid· with respect to each of
22462 * the {identity-constraint definitions} as per Identity-constraint
22463 * Satisfied (§3.11.4).
22464 */
22465 /*
22466 * Validate IDC keyrefs.
22467 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022468 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22469 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022470 /*
22471 * Merge/free the IDC table.
22472 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022473 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022474#ifdef DEBUG_IDC
22475 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022476 inode->nsName,
22477 inode->localName,
22478 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022479#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022480 if (vctxt->depth > 0) {
22481 /*
22482 * Merge the IDC node table with the table of the parent node.
22483 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022484 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22485 goto internal_error;
22486 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022487 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022488 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022489 * Clear the current ielem.
22490 * VAL TODO: Don't free the PSVI IDC tables if they are
22491 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022492 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022493 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022494 /*
22495 * Skip further processing if we are on the validation root.
22496 */
22497 if (vctxt->depth == 0) {
22498 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022499 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022500 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022501 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022502 /*
22503 * Reset the bubbleDepth if needed.
22504 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022505 if (vctxt->aidcs != NULL) {
22506 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22507 do {
22508 if (aidc->bubbleDepth == vctxt->depth) {
22509 /*
22510 * A bubbleDepth of a key/unique IDC matches the current
22511 * depth, this means that we are leaving the scope of the
22512 * top-most keyref IDC.
22513 */
22514 aidc->bubbleDepth = -1;
22515 }
22516 aidc = aidc->next;
22517 } while (aidc != NULL);
22518 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022519 vctxt->depth--;
22520 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022521 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022522 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022523 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22524 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022525 return (ret);
22526
22527internal_error:
22528 vctxt->err = -1;
22529 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022530}
22531
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022532/*
22533* 3.4.4 Complex Type Definition Validation Rules
22534* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22535*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022536static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022537xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022538{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022539 xmlSchemaNodeInfoPtr pielem;
22540 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022541 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022542
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022543 if (vctxt->depth <= 0) {
22544 VERROR_INT("xmlSchemaValidateChildElem",
22545 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022546 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022547 }
22548 pielem = vctxt->elemInfos[vctxt->depth -1];
22549 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22550 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022551 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022552 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022553 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022554 if (INODE_NILLED(pielem)) {
22555 /*
22556 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22557 */
22558 ACTIVATE_PARENT_ELEM;
22559 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22560 VERROR(ret, NULL,
22561 "Neither character nor element content is allowed, "
22562 "because the element was 'nilled'");
22563 ACTIVATE_ELEM;
22564 goto unexpected_elem;
22565 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022566
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022567 ptype = pielem->typeDef;
22568
22569 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22570 /*
22571 * Workaround for "anyType": we have currently no content model
22572 * assigned for "anyType", so handle it explicitely.
22573 * "anyType" has an unbounded, lax "any" wildcard.
22574 */
22575 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22576 vctxt->inode->localName,
22577 vctxt->inode->nsName);
22578
22579 if (vctxt->inode->decl == NULL) {
22580 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022581 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022582 * Process "xsi:type".
22583 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022584 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022585 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22586 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22587 if (iattr != NULL) {
22588 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22589 &(vctxt->inode->typeDef), NULL);
22590 if (ret != 0) {
22591 if (ret == -1) {
22592 VERROR_INT("xmlSchemaValidateChildElem",
22593 "calling xmlSchemaProcessXSIType() to "
22594 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022595 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022596 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022597 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022598 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022599 } else {
22600 /*
22601 * Fallback to "anyType".
22602 *
22603 * SPEC (cvc-assess-elt)
22604 * "If the item cannot be ·strictly assessed·, [...]
22605 * an element information item's schema validity may be laxly
22606 * assessed if its ·context-determined declaration· is not
22607 * skip by ·validating· with respect to the ·ur-type
22608 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22609 */
22610 vctxt->inode->typeDef =
22611 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022612 }
22613 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022614 return (0);
22615 }
22616
22617 switch (ptype->contentType) {
22618 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022619 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022620 * SPEC (2.1) "If the {content type} is empty, then the
22621 * element information item has no character or element
22622 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022623 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022624 ACTIVATE_PARENT_ELEM
22625 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22626 VERROR(ret, NULL,
22627 "Element content is not allowed, "
22628 "because the content type is empty");
22629 ACTIVATE_ELEM
22630 goto unexpected_elem;
22631 break;
22632
22633 case XML_SCHEMA_CONTENT_MIXED:
22634 case XML_SCHEMA_CONTENT_ELEMENTS: {
22635 xmlRegExecCtxtPtr regexCtxt;
22636 xmlChar *values[10];
22637 int terminal, nbval = 10, nbneg;
22638
22639 /* VAL TODO: Optimized "anyType" validation.*/
22640
22641 if (ptype->contModel == NULL) {
22642 VERROR_INT("xmlSchemaValidateChildElem",
22643 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022644 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022645 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022646 /*
22647 * Safety belf for evaluation if the cont. model was already
22648 * examined to be invalid.
22649 */
22650 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22651 VERROR_INT("xmlSchemaValidateChildElem",
22652 "validating elem, but elem content is already invalid");
22653 return (-1);
22654 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022655
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022656 regexCtxt = pielem->regexCtxt;
22657 if (regexCtxt == NULL) {
22658 /*
22659 * Create the regex context.
22660 */
22661 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22662 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22663 vctxt);
22664 if (regexCtxt == NULL) {
22665 VERROR_INT("xmlSchemaValidateChildElem",
22666 "failed to create a regex context");
22667 return (-1);
22668 }
22669 pielem->regexCtxt = regexCtxt;
22670#ifdef DEBUG_AUTOMATA
22671 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22672 pielem->localName);
22673#endif
22674 }
22675
22676 /*
22677 * SPEC (2.4) "If the {content type} is element-only or mixed,
22678 * then the sequence of the element information item's
22679 * element information item [children], if any, taken in
22680 * order, is ·valid· with respect to the {content type}'s
22681 * particle, as defined in Element Sequence Locally Valid
22682 * (Particle) (§3.9.4)."
22683 */
22684 ret = xmlRegExecPushString2(regexCtxt,
22685 vctxt->inode->localName,
22686 vctxt->inode->nsName,
22687 vctxt->inode);
22688#ifdef DEBUG_AUTOMATA
22689 if (ret < 0)
22690 xmlGenericError(xmlGenericErrorContext,
22691 "AUTOMATON push ERROR for '%s' on '%s'\n",
22692 vctxt->inode->localName, pielem->localName);
22693 else
22694 xmlGenericError(xmlGenericErrorContext,
22695 "AUTOMATON push OK for '%s' on '%s'\n",
22696 vctxt->inode->localName, pielem->localName);
22697#endif
22698 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22699 VERROR_INT("xmlSchemaValidateChildElem",
22700 "calling xmlRegExecPushString2()");
22701 return (-1);
22702 }
22703 if (ret < 0) {
22704 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22705 &values[0], &terminal);
22706 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22707 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22708 "This element is not expected",
22709 nbval, nbneg, values);
22710 ret = vctxt->err;
22711 goto unexpected_elem;
22712 } else
22713 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022714 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022715 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022716 case XML_SCHEMA_CONTENT_SIMPLE:
22717 case XML_SCHEMA_CONTENT_BASIC:
22718 ACTIVATE_PARENT_ELEM
22719 if (IS_COMPLEX_TYPE(ptype)) {
22720 /*
22721 * SPEC (cvc-complex-type) (2.2)
22722 * "If the {content type} is a simple type definition, then
22723 * the element information item has no element information
22724 * item [children], ..."
22725 */
22726 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22727 VERROR(ret, NULL, "Element content is not allowed, "
22728 "because the content type is a simple type definition");
22729 } else {
22730 /*
22731 * SPEC (cvc-type) (3.1.2) "The element information item must
22732 * have no element information item [children]."
22733 */
22734 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22735 VERROR(ret, NULL, "Element content is not allowed, "
22736 "because the type definition is simple");
22737 }
22738 ACTIVATE_ELEM
22739 ret = vctxt->err;
22740 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022741 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022742
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022743 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022744 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022745 }
22746 return (ret);
22747unexpected_elem:
22748 /*
22749 * Pop this element and set the skipDepth to skip
22750 * all further content of the parent element.
22751 */
22752 vctxt->skipDepth = vctxt->depth;
22753 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22754 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22755 return (ret);
22756}
22757
22758#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22759#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22760#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22761
22762static int
22763xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22764 int nodeType, const xmlChar *value, int len,
22765 int mode, int *consumed)
22766{
22767 /*
22768 * Unfortunately we have to duplicate the text sometimes.
22769 * OPTIMIZE: Maybe we could skip it, if:
22770 * 1. content type is simple
22771 * 2. whitespace is "collapse"
22772 * 3. it consists of whitespace only
22773 *
22774 * Process character content.
22775 */
22776 if (consumed != NULL)
22777 *consumed = 0;
22778 if (INODE_NILLED(vctxt->inode)) {
22779 /*
22780 * SPEC cvc-elt (3.3.4 - 3.2.1)
22781 * "The element information item must have no character or
22782 * element information item [children]."
22783 */
22784 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22785 "Neither character nor element content is allowed "
22786 "because the element is 'nilled'");
22787 return (vctxt->err);
22788 }
22789 /*
22790 * SPEC (2.1) "If the {content type} is empty, then the
22791 * element information item has no character or element
22792 * information item [children]."
22793 */
22794 if (vctxt->inode->typeDef->contentType ==
22795 XML_SCHEMA_CONTENT_EMPTY) {
22796 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22797 "Character content is not allowed, "
22798 "because the content type is empty");
22799 return (vctxt->err);
22800 }
22801
22802 if (vctxt->inode->typeDef->contentType ==
22803 XML_SCHEMA_CONTENT_ELEMENTS) {
22804 if ((nodeType != XML_TEXT_NODE) ||
22805 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22806 /*
22807 * SPEC cvc-complex-type (2.3)
22808 * "If the {content type} is element-only, then the
22809 * element information item has no character information
22810 * item [children] other than those whose [character
22811 * code] is defined as a white space in [XML 1.0 (Second
22812 * Edition)]."
22813 */
22814 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22815 "Character content other than whitespace is not allowed "
22816 "because the content type is 'element-only'");
22817 return (vctxt->err);
22818 }
22819 return (0);
22820 }
22821
22822 if ((value == NULL) || (value[0] == 0))
22823 return (0);
22824 /*
22825 * Save the value.
22826 * NOTE that even if the content type is *mixed*, we need the
22827 * *initial value* for default/fixed value constraints.
22828 */
22829 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22830 ((vctxt->inode->decl == NULL) ||
22831 (vctxt->inode->decl->value == NULL)))
22832 return (0);
22833
22834 if (vctxt->inode->value == NULL) {
22835 /*
22836 * Set the value.
22837 */
22838 switch (mode) {
22839 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22840 /*
22841 * When working on a tree.
22842 */
22843 vctxt->inode->value = value;
22844 break;
22845 case XML_SCHEMA_PUSH_TEXT_CREATED:
22846 /*
22847 * When working with the reader.
22848 * The value will be freed by the element info.
22849 */
22850 vctxt->inode->value = value;
22851 if (consumed != NULL)
22852 *consumed = 1;
22853 vctxt->inode->flags |=
22854 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22855 break;
22856 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22857 /*
22858 * When working with SAX.
22859 * The value will be freed by the element info.
22860 */
22861 if (len != -1)
22862 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22863 else
22864 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22865 vctxt->inode->flags |=
22866 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22867 break;
22868 default:
22869 break;
22870 }
22871 } else {
22872 /*
22873 * Concat the value.
22874 */
22875 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022876 vctxt->inode->value = BAD_CAST xmlStrncat(
22877 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022878 } else {
22879 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022880 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022881 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22882 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022883 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022884
22885 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022886}
22887
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022888static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022889xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022890{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022891 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022892
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022893 if ((vctxt->skipDepth != -1) &&
22894 (vctxt->depth >= vctxt->skipDepth)) {
22895 VERROR_INT("xmlSchemaValidateElem",
22896 "in skip-state");
22897 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022898 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022899 if (vctxt->xsiAssemble) {
22900 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22901 goto internal_error;
22902 }
22903 if (vctxt->depth > 0) {
22904 /*
22905 * Validate this element against the content model
22906 * of the parent.
22907 */
22908 ret = xmlSchemaValidateChildElem(vctxt);
22909 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022910 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022911 VERROR_INT("xmlSchemaValidateElem",
22912 "calling xmlSchemaStreamValidateChildElement()");
22913 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022914 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022915 goto exit;
22916 }
22917 if (vctxt->depth == vctxt->skipDepth)
22918 goto exit;
22919 if ((vctxt->inode->decl == NULL) &&
22920 (vctxt->inode->typeDef == NULL)) {
22921 VERROR_INT("xmlSchemaValidateElem",
22922 "the child element was valid but neither the "
22923 "declaration nor the type was set");
22924 goto internal_error;
22925 }
22926 } else {
22927 /*
22928 * Get the declaration of the validation root.
22929 */
22930 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22931 vctxt->inode->localName,
22932 vctxt->inode->nsName);
22933 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022934 ret = XML_SCHEMAV_CVC_ELT_1;
22935 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022936 "No matching global declaration available "
22937 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022938 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022939 }
22940 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022941
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022942 if (vctxt->inode->decl == NULL)
22943 goto type_validation;
22944
22945 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22946 int skip;
22947 /*
22948 * Wildcards.
22949 */
22950 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22951 if (ret != 0) {
22952 if (ret < 0) {
22953 VERROR_INT("xmlSchemaValidateElem",
22954 "calling xmlSchemaValidateElemWildcard()");
22955 goto internal_error;
22956 }
22957 goto exit;
22958 }
22959 if (skip) {
22960 vctxt->skipDepth = vctxt->depth;
22961 goto exit;
22962 }
22963 /*
22964 * The declaration might be set by the wildcard validation,
22965 * when the processContents is "lax" or "strict".
22966 */
22967 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22968 /*
22969 * Clear the "decl" field to not confuse further processing.
22970 */
22971 vctxt->inode->decl = NULL;
22972 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022973 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022974 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022975 /*
22976 * Validate against the declaration.
22977 */
22978 ret = xmlSchemaValidateElemDecl(vctxt);
22979 if (ret != 0) {
22980 if (ret < 0) {
22981 VERROR_INT("xmlSchemaValidateElem",
22982 "calling xmlSchemaValidateElemDecl()");
22983 goto internal_error;
22984 }
22985 goto exit;
22986 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022987 /*
22988 * Validate against the type definition.
22989 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022990type_validation:
22991
22992 if (vctxt->inode->typeDef == NULL) {
22993 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22994 ret = XML_SCHEMAV_CVC_TYPE_1;
22995 VERROR(ret, NULL,
22996 "The type definition is absent");
22997 goto exit;
22998 }
22999 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
23000 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
23001 ret = XML_SCHEMAV_CVC_TYPE_2;
23002 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023003 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023004 goto exit;
23005 }
23006 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023007 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023008 * during validation against the declaration. This must be done
23009 * _before_ attribute validation.
23010 */
23011 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
23012 if (ret == -1) {
23013 VERROR_INT("xmlSchemaValidateElem",
23014 "calling xmlSchemaXPathEvaluate()");
23015 goto internal_error;
23016 }
23017 /*
23018 * Validate attributes.
23019 */
23020 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
23021 if ((vctxt->nbAttrInfos != 0) ||
23022 (vctxt->inode->typeDef->attributeUses != NULL)) {
23023
23024 ret = xmlSchemaVAttributesComplex(vctxt);
23025 }
23026 } else if (vctxt->nbAttrInfos != 0) {
23027
23028 ret = xmlSchemaVAttributesSimple(vctxt);
23029 }
23030 /*
23031 * Clear registered attributes.
23032 */
23033 if (vctxt->nbAttrInfos != 0)
23034 xmlSchemaClearAttrInfos(vctxt);
23035 if (ret == -1) {
23036 VERROR_INT("xmlSchemaValidateElem",
23037 "calling attributes validation");
23038 goto internal_error;
23039 }
23040 /*
23041 * Don't return an error if attributes are invalid on purpose.
23042 */
23043 ret = 0;
23044
23045exit:
23046 if (ret != 0)
23047 vctxt->skipDepth = vctxt->depth;
23048 return (ret);
23049internal_error:
23050 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023051}
23052
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023053#ifdef XML_SCHEMA_READER_ENABLED
23054static int
23055xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023056{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023057 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
23058 int depth, nodeType, ret = 0, consumed;
23059 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023060
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023061 vctxt->depth = -1;
23062 ret = xmlTextReaderRead(vctxt->reader);
23063 /*
23064 * Move to the document element.
23065 */
23066 while (ret == 1) {
23067 nodeType = xmlTextReaderNodeType(vctxt->reader);
23068 if (nodeType == XML_ELEMENT_NODE)
23069 goto root_found;
23070 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023071 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023072 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023073
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023074root_found:
23075
23076 do {
23077 depth = xmlTextReaderDepth(vctxt->reader);
23078 nodeType = xmlTextReaderNodeType(vctxt->reader);
23079
23080 if (nodeType == XML_ELEMENT_NODE) {
23081
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023082 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023083 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23084 VERROR_INT("xmlSchemaVReaderWalk",
23085 "calling xmlSchemaValidatorPushElem()");
23086 goto internal_error;
23087 }
23088 ielem = vctxt->inode;
23089 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23090 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23091 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23092 /*
23093 * Is the element empty?
23094 */
23095 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23096 if (ret == -1) {
23097 VERROR_INT("xmlSchemaVReaderWalk",
23098 "calling xmlTextReaderIsEmptyElement()");
23099 goto internal_error;
23100 }
23101 if (ret) {
23102 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23103 }
23104 /*
23105 * Register attributes.
23106 */
23107 vctxt->nbAttrInfos = 0;
23108 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23109 if (ret == -1) {
23110 VERROR_INT("xmlSchemaVReaderWalk",
23111 "calling xmlTextReaderMoveToFirstAttribute()");
23112 goto internal_error;
23113 }
23114 if (ret == 1) {
23115 do {
23116 /*
23117 * VAL TODO: How do we know that the reader works on a
23118 * node tree, to be able to pass a node here?
23119 */
23120 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23121 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23122 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23123 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23124
23125 VERROR_INT("xmlSchemaVReaderWalk",
23126 "calling xmlSchemaValidatorPushAttribute()");
23127 goto internal_error;
23128 }
23129 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23130 if (ret == -1) {
23131 VERROR_INT("xmlSchemaVReaderWalk",
23132 "calling xmlTextReaderMoveToFirstAttribute()");
23133 goto internal_error;
23134 }
23135 } while (ret == 1);
23136 /*
23137 * Back to element position.
23138 */
23139 ret = xmlTextReaderMoveToElement(vctxt->reader);
23140 if (ret == -1) {
23141 VERROR_INT("xmlSchemaVReaderWalk",
23142 "calling xmlTextReaderMoveToElement()");
23143 goto internal_error;
23144 }
23145 }
23146 /*
23147 * Validate the element.
23148 */
23149 ret= xmlSchemaValidateElem(vctxt);
23150 if (ret != 0) {
23151 if (ret == -1) {
23152 VERROR_INT("xmlSchemaVReaderWalk",
23153 "calling xmlSchemaValidateElem()");
23154 goto internal_error;
23155 }
23156 goto exit;
23157 }
23158 if (vctxt->depth == vctxt->skipDepth) {
23159 int curDepth;
23160 /*
23161 * Skip all content.
23162 */
23163 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23164 ret = xmlTextReaderRead(vctxt->reader);
23165 curDepth = xmlTextReaderDepth(vctxt->reader);
23166 while ((ret == 1) && (curDepth != depth)) {
23167 ret = xmlTextReaderRead(vctxt->reader);
23168 curDepth = xmlTextReaderDepth(vctxt->reader);
23169 }
23170 if (ret < 0) {
23171 /*
23172 * VAL TODO: A reader error occured; what to do here?
23173 */
23174 ret = 1;
23175 goto exit;
23176 }
23177 }
23178 goto leave_elem;
23179 }
23180 /*
23181 * READER VAL TODO: Is an END_ELEM really never called
23182 * if the elem is empty?
23183 */
23184 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23185 goto leave_elem;
23186 } else if (nodeType == END_ELEM) {
23187 /*
23188 * Process END of element.
23189 */
23190leave_elem:
23191 ret = xmlSchemaValidatorPopElem(vctxt);
23192 if (ret != 0) {
23193 if (ret < 0) {
23194 VERROR_INT("xmlSchemaVReaderWalk",
23195 "calling xmlSchemaValidatorPopElem()");
23196 goto internal_error;
23197 }
23198 goto exit;
23199 }
23200 if (vctxt->depth >= 0)
23201 ielem = vctxt->inode;
23202 else
23203 ielem = NULL;
23204 } else if ((nodeType == XML_TEXT_NODE) ||
23205 (nodeType == XML_CDATA_SECTION_NODE) ||
23206 (nodeType == WHTSP) ||
23207 (nodeType == SIGN_WHTSP)) {
23208 /*
23209 * Process character content.
23210 */
23211 xmlChar *value;
23212
23213 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23214 nodeType = XML_TEXT_NODE;
23215
23216 value = xmlTextReaderValue(vctxt->reader);
23217 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23218 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23219 if (! consumed)
23220 xmlFree(value);
23221 if (ret == -1) {
23222 VERROR_INT("xmlSchemaVReaderWalk",
23223 "calling xmlSchemaVPushText()");
23224 goto internal_error;
23225 }
23226 } else if ((nodeType == XML_ENTITY_NODE) ||
23227 (nodeType == XML_ENTITY_REF_NODE)) {
23228 /*
23229 * VAL TODO: What to do with entities?
23230 */
23231 TODO
23232 }
23233 /*
23234 * Read next node.
23235 */
23236 ret = xmlTextReaderRead(vctxt->reader);
23237 } while (ret == 1);
23238
23239exit:
23240 return (ret);
23241internal_error:
23242 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023243}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023244#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023245
23246/************************************************************************
23247 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023248 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023249 * *
23250 ************************************************************************/
23251
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023252#ifdef XML_SCHEMA_SAX_ENABLED
23253/*
23254* Process text content.
23255*/
23256static void
23257xmlSchemaSAXHandleText(void *ctx,
23258 const xmlChar * ch,
23259 int len)
23260{
23261 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23262
23263 if (vctxt->depth < 0)
23264 return;
23265 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23266 return;
23267 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23268 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23269 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23270 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23271 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23272 "calling xmlSchemaVPushText()");
23273 vctxt->err = -1;
23274 xmlStopParser(vctxt->parserCtxt);
23275 }
23276}
23277
23278/*
23279* Process CDATA content.
23280*/
23281static void
23282xmlSchemaSAXHandleCDataSection(void *ctx,
23283 const xmlChar * ch,
23284 int len)
23285{
23286 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23287
23288 if (vctxt->depth < 0)
23289 return;
23290 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23291 return;
23292 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23293 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23294 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23295 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23296 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23297 "calling xmlSchemaVPushText()");
23298 vctxt->err = -1;
23299 xmlStopParser(vctxt->parserCtxt);
23300 }
23301}
23302
23303static void
23304xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23305 const xmlChar * name ATTRIBUTE_UNUSED)
23306{
23307 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23308
23309 if (vctxt->depth < 0)
23310 return;
23311 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23312 return;
23313 /* SAX VAL TODO: What to do here? */
23314 TODO
23315}
23316
23317static void
23318xmlSchemaSAXHandleStartElementNs(void *ctx,
23319 const xmlChar * localname,
23320 const xmlChar * prefix ATTRIBUTE_UNUSED,
23321 const xmlChar * URI,
23322 int nb_namespaces,
23323 const xmlChar ** namespaces,
23324 int nb_attributes,
23325 int nb_defaulted ATTRIBUTE_UNUSED,
23326 const xmlChar ** attributes)
23327{
23328 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23329 int ret;
23330 xmlSchemaNodeInfoPtr ielem;
23331 int i, j;
23332
23333 /*
23334 * SAX VAL TODO: What to do with nb_defaulted?
23335 */
23336 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023337 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023338 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023339 vctxt->depth++;
23340 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023341 return;
23342 /*
23343 * Push the element.
23344 */
23345 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23346 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23347 "calling xmlSchemaValidatorPushElem()");
23348 goto internal_error;
23349 }
23350 ielem = vctxt->inode;
23351 ielem->localName = localname;
23352 ielem->nsName = URI;
23353 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23354 /*
23355 * Register namespaces on the elem info.
23356 */
23357 if (nb_namespaces != 0) {
23358 /*
23359 * Although the parser builds its own namespace list,
23360 * we have no access to it, so we'll use an own one.
23361 */
23362 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23363 /*
23364 * Store prefix and namespace name.
23365 */
23366 if (ielem->nsBindings == NULL) {
23367 ielem->nsBindings =
23368 (const xmlChar **) xmlMalloc(10 *
23369 sizeof(const xmlChar *));
23370 if (ielem->nsBindings == NULL) {
23371 xmlSchemaVErrMemory(vctxt,
23372 "allocating namespace bindings for SAX validation",
23373 NULL);
23374 goto internal_error;
23375 }
23376 ielem->nbNsBindings = 0;
23377 ielem->sizeNsBindings = 5;
23378 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23379 ielem->sizeNsBindings *= 2;
23380 ielem->nsBindings =
23381 (const xmlChar **) xmlRealloc(
23382 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023383 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023384 if (ielem->nsBindings == NULL) {
23385 xmlSchemaVErrMemory(vctxt,
23386 "re-allocating namespace bindings for SAX validation",
23387 NULL);
23388 goto internal_error;
23389 }
23390 }
23391
23392 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23393 if (namespaces[j+1][0] == 0) {
23394 /*
23395 * Handle xmlns="".
23396 */
23397 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23398 } else
23399 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23400 namespaces[j+1];
23401 ielem->nbNsBindings++;
23402 }
23403 }
23404 /*
23405 * Register attributes.
23406 * SAX VAL TODO: We are not adding namespace declaration
23407 * attributes yet.
23408 */
23409 if (nb_attributes != 0) {
23410 xmlChar *value;
23411
23412 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23413 /*
23414 * Duplicate the value.
23415 */
23416 value = xmlStrndup(attributes[j+3],
23417 attributes[j+4] - attributes[j+3]);
23418 ret = xmlSchemaValidatorPushAttribute(vctxt,
23419 NULL, attributes[j], attributes[j+2], 0,
23420 value, 1);
23421 if (ret == -1) {
23422 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23423 "calling xmlSchemaValidatorPushAttribute()");
23424 goto internal_error;
23425 }
23426 }
23427 }
23428 /*
23429 * Validate the element.
23430 */
23431 ret = xmlSchemaValidateElem(vctxt);
23432 if (ret != 0) {
23433 if (ret == -1) {
23434 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23435 "calling xmlSchemaValidateElem()");
23436 goto internal_error;
23437 }
23438 goto exit;
23439 }
23440
23441exit:
23442 return;
23443internal_error:
23444 vctxt->err = -1;
23445 xmlStopParser(vctxt->parserCtxt);
23446 return;
23447}
23448
23449static void
23450xmlSchemaSAXHandleEndElementNs(void *ctx,
23451 const xmlChar * localname ATTRIBUTE_UNUSED,
23452 const xmlChar * prefix ATTRIBUTE_UNUSED,
23453 const xmlChar * URI ATTRIBUTE_UNUSED)
23454{
23455 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23456 int res;
23457
23458 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023459 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023460 */
23461 if (vctxt->skipDepth != -1) {
23462 if (vctxt->depth > vctxt->skipDepth) {
23463 vctxt->depth--;
23464 return;
23465 } else
23466 vctxt->skipDepth = -1;
23467 }
23468 /*
23469 * SAX VAL TODO: Just a temporary check.
23470 */
23471 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23472 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23473 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23474 "elem pop mismatch");
23475 }
23476 res = xmlSchemaValidatorPopElem(vctxt);
23477 if (res != 0) {
23478 if (res < 0) {
23479 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23480 "calling xmlSchemaValidatorPopElem()");
23481 goto internal_error;
23482 }
23483 goto exit;
23484 }
23485exit:
23486 return;
23487internal_error:
23488 vctxt->err = -1;
23489 xmlStopParser(vctxt->parserCtxt);
23490 return;
23491}
23492#endif
23493
Daniel Veillard4255d502002-04-16 15:50:10 +000023494/************************************************************************
23495 * *
23496 * Validation interfaces *
23497 * *
23498 ************************************************************************/
23499
23500/**
23501 * xmlSchemaNewValidCtxt:
23502 * @schema: a precompiled XML Schemas
23503 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023504 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023505 *
23506 * Returns the validation context or NULL in case of error
23507 */
23508xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023509xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23510{
Daniel Veillard4255d502002-04-16 15:50:10 +000023511 xmlSchemaValidCtxtPtr ret;
23512
23513 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23514 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023515 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023516 return (NULL);
23517 }
23518 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023519 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23520 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023521 return (ret);
23522}
23523
23524/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023525 * xmlSchemaClearValidCtxt:
23526 * @ctxt: the schema validation context
23527 *
23528 * Free the resources associated to the schema validation context;
23529 * leaves some fields alive intended for reuse of the context.
23530 */
23531static void
23532xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23533{
23534 if (vctxt == NULL)
23535 return;
23536
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023537 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023538 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023539 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023540#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023541 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023542#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023543 if (vctxt->value != NULL) {
23544 xmlSchemaFreeValue(vctxt->value);
23545 vctxt->value = NULL;
23546 }
23547 /*
23548 * Augmented IDC information.
23549 */
23550 if (vctxt->aidcs != NULL) {
23551 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23552 do {
23553 next = cur->next;
23554 xmlFree(cur);
23555 cur = next;
23556 } while (cur != NULL);
23557 vctxt->aidcs = NULL;
23558 }
23559 if (vctxt->idcNodes != NULL) {
23560 int i;
23561 xmlSchemaPSVIIDCNodePtr item;
23562
23563 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023564 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023565 xmlFree(item->keys);
23566 xmlFree(item);
23567 }
23568 xmlFree(vctxt->idcNodes);
23569 vctxt->idcNodes = NULL;
23570 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023571 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023572 * Note that we won't delete the XPath state pool here.
23573 */
23574 if (vctxt->xpathStates != NULL) {
23575 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23576 vctxt->xpathStates = NULL;
23577 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023578 /*
23579 * Attribute info.
23580 */
23581 if (vctxt->nbAttrInfos != 0) {
23582 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023583 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023584 /*
23585 * Element info.
23586 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023587 if (vctxt->elemInfos != NULL) {
23588 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023589 xmlSchemaNodeInfoPtr ei;
23590
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023591 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023592 ei = vctxt->elemInfos[i];
23593 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023594 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023595 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023596 }
23597 }
23598}
23599
23600/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023601 * xmlSchemaFreeValidCtxt:
23602 * @ctxt: the schema validation context
23603 *
23604 * Free the resources associated to the schema validation context
23605 */
23606void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023607xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23608{
Daniel Veillard4255d502002-04-16 15:50:10 +000023609 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023610 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023611 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023612 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023613 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023614 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023615 if (ctxt->idcNodes != NULL) {
23616 int i;
23617 xmlSchemaPSVIIDCNodePtr item;
23618
23619 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023620 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023621 xmlFree(item->keys);
23622 xmlFree(item);
23623 }
23624 xmlFree(ctxt->idcNodes);
23625 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023626 if (ctxt->idcKeys != NULL) {
23627 int i;
23628 for (i = 0; i < ctxt->nbIdcKeys; i++)
23629 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23630 xmlFree(ctxt->idcKeys);
23631 }
23632
23633 if (ctxt->xpathStates != NULL)
23634 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23635 if (ctxt->xpathStatePool != NULL)
23636 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23637
23638 /*
23639 * Augmented IDC information.
23640 */
23641 if (ctxt->aidcs != NULL) {
23642 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23643 do {
23644 next = cur->next;
23645 xmlFree(cur);
23646 cur = next;
23647 } while (cur != NULL);
23648 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023649 if (ctxt->attrInfos != NULL) {
23650 int i;
23651 xmlSchemaAttrInfoPtr attr;
23652
23653 /* Just a paranoid call to the cleanup. */
23654 if (ctxt->nbAttrInfos != 0)
23655 xmlSchemaClearAttrInfos(ctxt);
23656 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23657 attr = ctxt->attrInfos[i];
23658 xmlFree(attr);
23659 }
23660 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023661 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023662 if (ctxt->elemInfos != NULL) {
23663 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023664 xmlSchemaNodeInfoPtr ei;
23665
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023666 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023667 ei = ctxt->elemInfos[i];
23668 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023669 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023670 xmlSchemaClearElemInfo(ei);
23671 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023672 }
23673 xmlFree(ctxt->elemInfos);
23674 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023675 if (ctxt->dict != NULL)
23676 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023677 xmlFree(ctxt);
23678}
23679
23680/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000023681 * xmlSchemaIsValid:
23682 * @ctxt: the schema validation context
23683 *
23684 * Check if any error was detected during validation.
23685 *
23686 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
23687 * of internal error.
23688 */
23689int
23690xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
23691{
23692 if (ctxt == NULL)
23693 return(-1);
23694 return(ctxt->err == 0);
23695}
23696
23697/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023698 * xmlSchemaSetValidErrors:
23699 * @ctxt: a schema validation context
23700 * @err: the error function
23701 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023702 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023703 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023704 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023705 */
23706void
23707xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023708 xmlSchemaValidityErrorFunc err,
23709 xmlSchemaValidityWarningFunc warn, void *ctx)
23710{
Daniel Veillard4255d502002-04-16 15:50:10 +000023711 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023712 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023713 ctxt->error = err;
23714 ctxt->warning = warn;
23715 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023716 if (ctxt->pctxt != NULL)
23717 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023718}
23719
23720/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000023721 * xmlSchemaSetValidStructuredErrors:
23722 * @ctxt: a schema validation context
23723 * @serror: the structured error function
23724 * @ctx: the functions context
23725 *
23726 * Set the structured error callback
23727 */
23728void
23729xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
23730 xmlStructuredErrorFunc serror, void *ctx)
23731{
23732 if (ctxt == NULL)
23733 return;
23734 ctxt->serror = serror;
23735 ctxt->error = NULL;
23736 ctxt->warning = NULL;
23737 ctxt->userData = ctx;
23738}
23739
23740/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023741 * xmlSchemaGetValidErrors:
23742 * @ctxt: a XML-Schema validation context
23743 * @err: the error function result
23744 * @warn: the warning function result
23745 * @ctx: the functions context result
23746 *
23747 * Get the error and warning callback informations
23748 *
23749 * Returns -1 in case of error and 0 otherwise
23750 */
23751int
23752xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23753 xmlSchemaValidityErrorFunc * err,
23754 xmlSchemaValidityWarningFunc * warn, void **ctx)
23755{
23756 if (ctxt == NULL)
23757 return (-1);
23758 if (err != NULL)
23759 *err = ctxt->error;
23760 if (warn != NULL)
23761 *warn = ctxt->warning;
23762 if (ctx != NULL)
23763 *ctx = ctxt->userData;
23764 return (0);
23765}
23766
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023767
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023768/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023769 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023770 * @ctxt: a schema validation context
23771 * @options: a combination of xmlSchemaValidOption
23772 *
23773 * Sets the options to be used during the validation.
23774 *
23775 * Returns 0 in case of success, -1 in case of an
23776 * API error.
23777 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023778int
23779xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23780 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023781
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023782{
23783 int i;
23784
23785 if (ctxt == NULL)
23786 return (-1);
23787 /*
23788 * WARNING: Change the start value if adding to the
23789 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023790 * TODO: Is there an other, more easy to maintain,
23791 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023792 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023793 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023794 if (options & 1<<i)
23795 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023796 }
23797 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023798 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023799}
23800
23801/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023802 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023803 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023804 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023805 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023806 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023807 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023808 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023809int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023810xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023811
23812{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023813 if (ctxt == NULL)
23814 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023815 else
23816 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023817}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023818
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023819static int
23820xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23821{
23822 xmlAttrPtr attr;
23823 int ret = 0;
23824 xmlSchemaNodeInfoPtr ielem = NULL;
23825 xmlNodePtr node, valRoot;
23826 const xmlChar *nsName;
23827
23828 /* DOC VAL TODO: Move this to the start function. */
23829 valRoot = xmlDocGetRootElement(vctxt->doc);
23830 if (valRoot == NULL) {
23831 /* VAL TODO: Error code? */
23832 VERROR(1, NULL, "The document has no document element");
23833 return (1);
23834 }
23835 vctxt->depth = -1;
23836 vctxt->validationRoot = valRoot;
23837 node = valRoot;
23838 while (node != NULL) {
23839 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23840 goto next_sibling;
23841 if (node->type == XML_ELEMENT_NODE) {
23842
23843 /*
23844 * Init the node-info.
23845 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023846 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023847 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23848 goto internal_error;
23849 ielem = vctxt->inode;
23850 ielem->node = node;
23851 ielem->localName = node->name;
23852 if (node->ns != NULL)
23853 ielem->nsName = node->ns->href;
23854 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23855 /*
23856 * Register attributes.
23857 * DOC VAL TODO: We do not register namespace declaration
23858 * attributes yet.
23859 */
23860 vctxt->nbAttrInfos = 0;
23861 if (node->properties != NULL) {
23862 attr = node->properties;
23863 do {
23864 if (attr->ns != NULL)
23865 nsName = attr->ns->href;
23866 else
23867 nsName = NULL;
23868 ret = xmlSchemaValidatorPushAttribute(vctxt,
23869 (xmlNodePtr) attr,
23870 attr->name, nsName, 0,
23871 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23872 if (ret == -1) {
23873 VERROR_INT("xmlSchemaDocWalk",
23874 "calling xmlSchemaValidatorPushAttribute()");
23875 goto internal_error;
23876 }
23877 attr = attr->next;
23878 } while (attr);
23879 }
23880 /*
23881 * Validate the element.
23882 */
23883 ret = xmlSchemaValidateElem(vctxt);
23884 if (ret != 0) {
23885 if (ret == -1) {
23886 VERROR_INT("xmlSchemaDocWalk",
23887 "calling xmlSchemaValidateElem()");
23888 goto internal_error;
23889 }
23890 /*
23891 * Don't stop validation; just skip the content
23892 * of this element.
23893 */
23894 goto leave_node;
23895 }
23896 if ((vctxt->skipDepth != -1) &&
23897 (vctxt->depth >= vctxt->skipDepth))
23898 goto leave_node;
23899 } else if ((node->type == XML_TEXT_NODE) ||
23900 (node->type == XML_CDATA_SECTION_NODE)) {
23901 /*
23902 * Process character content.
23903 */
23904 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23905 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23906 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23907 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23908 if (ret < 0) {
23909 VERROR_INT("xmlSchemaVDocWalk",
23910 "calling xmlSchemaVPushText()");
23911 goto internal_error;
23912 }
23913 /*
23914 * DOC VAL TODO: Should we skip further validation of the
23915 * element content here?
23916 */
23917 } else if ((node->type == XML_ENTITY_NODE) ||
23918 (node->type == XML_ENTITY_REF_NODE)) {
23919 /*
23920 * DOC VAL TODO: What to do with entities?
23921 */
23922 TODO
23923 } else {
23924 goto leave_node;
23925 /*
23926 * DOC VAL TODO: XInclude nodes, etc.
23927 */
23928 }
23929 /*
23930 * Walk the doc.
23931 */
23932 if (node->children != NULL) {
23933 node = node->children;
23934 continue;
23935 }
23936leave_node:
23937 if (node->type == XML_ELEMENT_NODE) {
23938 /*
23939 * Leaving the scope of an element.
23940 */
23941 if (node != vctxt->inode->node) {
23942 VERROR_INT("xmlSchemaVDocWalk",
23943 "element position mismatch");
23944 goto internal_error;
23945 }
23946 ret = xmlSchemaValidatorPopElem(vctxt);
23947 if (ret != 0) {
23948 if (ret < 0) {
23949 VERROR_INT("xmlSchemaVDocWalk",
23950 "calling xmlSchemaValidatorPopElem()");
23951 goto internal_error;
23952 }
23953 }
23954 if (node == valRoot)
23955 goto exit;
23956 }
23957next_sibling:
23958 if (node->next != NULL)
23959 node = node->next;
23960 else {
23961 node = node->parent;
23962 goto leave_node;
23963 }
23964 }
23965
23966exit:
23967 return (ret);
23968internal_error:
23969 return (-1);
23970}
23971
23972static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000023973xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023974 /*
23975 * Some initialization.
23976 */
23977 vctxt->err = 0;
23978 vctxt->nberrors = 0;
23979 vctxt->depth = -1;
23980 vctxt->skipDepth = -1;
23981 /*
23982 * Create a schema + parser if necessary.
23983 */
23984 if (vctxt->schema == NULL) {
23985
23986 if ((vctxt->pctxt == NULL) &&
23987 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23988 return (-1);
23989
23990 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23991 if (vctxt->schema == NULL) {
23992 VERROR_INT("xmlSchemaVStartValidation",
23993 "creating a schema");
23994 return (-1);
23995 }
23996 vctxt->xsiAssemble = 1;
23997 } else
23998 vctxt->xsiAssemble = 0;
23999 /*
24000 * Augment the IDC definitions.
24001 */
24002 if (vctxt->schema->idcDef != NULL) {
24003 xmlHashScan(vctxt->schema->idcDef,
24004 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
24005 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000024006 return(0);
24007}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024008
Daniel Veillardf10ae122005-07-10 19:03:16 +000024009static void
24010xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024011 if (vctxt->xsiAssemble) {
24012 if (vctxt->schema != NULL) {
24013 xmlSchemaFree(vctxt->schema);
24014 vctxt->schema = NULL;
24015 }
24016 }
24017 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024018}
24019
24020static int
24021xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
24022{
24023 int ret = 0;
24024
24025 if (xmlSchemaPreRun(vctxt) < 0)
24026 return(-1);
24027
24028 if (vctxt->doc != NULL) {
24029 /*
24030 * Tree validation.
24031 */
24032 ret = xmlSchemaVDocWalk(vctxt);
24033#ifdef LIBXML_READER_ENABLED
24034 } else if (vctxt->reader != NULL) {
24035 /*
24036 * XML Reader validation.
24037 */
24038#ifdef XML_SCHEMA_READER_ENABLED
24039 ret = xmlSchemaVReaderWalk(vctxt);
24040#endif
24041#endif
24042 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
24043 /*
24044 * SAX validation.
24045 */
24046 ret = xmlParseDocument(vctxt->parserCtxt);
24047 } else {
24048 VERROR_INT("xmlSchemaVStartValidation",
24049 "no instance to validate");
24050 ret = -1;
24051 }
24052
24053 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024054 if (ret == 0)
24055 ret = vctxt->err;
24056 return (ret);
24057}
24058
24059/**
24060 * xmlSchemaValidateOneElement:
24061 * @ctxt: a schema validation context
24062 * @elem: an element node
24063 *
24064 * Validate a branch of a tree, starting with the given @elem.
24065 *
24066 * Returns 0 if the element and its subtree is valid, a positive error
24067 * code number otherwise and -1 in case of an internal or API error.
24068 */
24069int
24070xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24071{
24072 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24073 return (-1);
24074
24075 if (ctxt->schema == NULL)
24076 return (-1);
24077
24078 ctxt->doc = elem->doc;
24079 ctxt->node = elem;
24080 ctxt->validationRoot = elem;
24081 return(xmlSchemaVStart(ctxt));
24082}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024083
Daniel Veillard259f0df2004-08-18 09:13:18 +000024084/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024085 * xmlSchemaValidateDoc:
24086 * @ctxt: a schema validation context
24087 * @doc: a parsed document tree
24088 *
24089 * Validate a document tree in memory.
24090 *
24091 * Returns 0 if the document is schemas valid, a positive error code
24092 * number otherwise and -1 in case of internal or API error.
24093 */
24094int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024095xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24096{
Daniel Veillard4255d502002-04-16 15:50:10 +000024097 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024098 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024099
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024100 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024101 ctxt->node = xmlDocGetRootElement(doc);
24102 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024103 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024104 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24105 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024106 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024107 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024108 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024109 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024110 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024111}
24112
Daniel Veillardcdc82732005-07-08 15:04:06 +000024113
24114/************************************************************************
24115 * *
24116 * Function and data for SAX streaming API *
24117 * *
24118 ************************************************************************/
24119typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24120typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24121
24122struct _xmlSchemaSplitSAXData {
24123 xmlSAXHandlerPtr user_sax;
24124 void *user_data;
24125 xmlSchemaValidCtxtPtr ctxt;
24126 xmlSAXHandlerPtr schemas_sax;
24127};
24128
Daniel Veillard971771e2005-07-09 17:32:57 +000024129#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24130
24131struct _xmlSchemaSAXPlug {
24132 unsigned int magic;
24133
24134 /* the original callbacks informations */
24135 xmlSAXHandlerPtr *user_sax_ptr;
24136 xmlSAXHandlerPtr user_sax;
24137 void **user_data_ptr;
24138 void *user_data;
24139
24140 /* the block plugged back and validation informations */
24141 xmlSAXHandler schemas_sax;
24142 xmlSchemaValidCtxtPtr ctxt;
24143};
24144
Daniel Veillardcdc82732005-07-08 15:04:06 +000024145/* All those functions just bounces to the user provided SAX handlers */
24146static void
24147internalSubsetSplit(void *ctx, const xmlChar *name,
24148 const xmlChar *ExternalID, const xmlChar *SystemID)
24149{
Daniel Veillard971771e2005-07-09 17:32:57 +000024150 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024151 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24152 (ctxt->user_sax->internalSubset != NULL))
24153 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24154 SystemID);
24155}
24156
24157static int
24158isStandaloneSplit(void *ctx)
24159{
Daniel Veillard971771e2005-07-09 17:32:57 +000024160 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024161 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24162 (ctxt->user_sax->isStandalone != NULL))
24163 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24164 return(0);
24165}
24166
24167static int
24168hasInternalSubsetSplit(void *ctx)
24169{
Daniel Veillard971771e2005-07-09 17:32:57 +000024170 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024171 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24172 (ctxt->user_sax->hasInternalSubset != NULL))
24173 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24174 return(0);
24175}
24176
24177static int
24178hasExternalSubsetSplit(void *ctx)
24179{
Daniel Veillard971771e2005-07-09 17:32:57 +000024180 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024181 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24182 (ctxt->user_sax->hasExternalSubset != NULL))
24183 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24184 return(0);
24185}
24186
24187static void
24188externalSubsetSplit(void *ctx, const xmlChar *name,
24189 const xmlChar *ExternalID, const xmlChar *SystemID)
24190{
Daniel Veillard971771e2005-07-09 17:32:57 +000024191 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024192 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24193 (ctxt->user_sax->internalSubset != NULL))
24194 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24195 SystemID);
24196}
24197
24198static xmlParserInputPtr
24199resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24200{
Daniel Veillard971771e2005-07-09 17:32:57 +000024201 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024202 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24203 (ctxt->user_sax->resolveEntity != NULL))
24204 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24205 systemId));
24206 return(NULL);
24207}
24208
24209static xmlEntityPtr
24210getEntitySplit(void *ctx, const xmlChar *name)
24211{
Daniel Veillard971771e2005-07-09 17:32:57 +000024212 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024213 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24214 (ctxt->user_sax->getEntity != NULL))
24215 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24216 return(NULL);
24217}
24218
24219static xmlEntityPtr
24220getParameterEntitySplit(void *ctx, const xmlChar *name)
24221{
Daniel Veillard971771e2005-07-09 17:32:57 +000024222 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024223 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24224 (ctxt->user_sax->getParameterEntity != NULL))
24225 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24226 return(NULL);
24227}
24228
24229
24230static void
24231entityDeclSplit(void *ctx, const xmlChar *name, int type,
24232 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24233{
Daniel Veillard971771e2005-07-09 17:32:57 +000024234 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024235 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24236 (ctxt->user_sax->entityDecl != NULL))
24237 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24238 systemId, content);
24239}
24240
24241static void
24242attributeDeclSplit(void *ctx, const xmlChar * elem,
24243 const xmlChar * name, int type, int def,
24244 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24245{
Daniel Veillard971771e2005-07-09 17:32:57 +000024246 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024247 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24248 (ctxt->user_sax->attributeDecl != NULL)) {
24249 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24250 def, defaultValue, tree);
24251 } else {
24252 xmlFreeEnumeration(tree);
24253 }
24254}
24255
24256static void
24257elementDeclSplit(void *ctx, const xmlChar *name, int type,
24258 xmlElementContentPtr content)
24259{
Daniel Veillard971771e2005-07-09 17:32:57 +000024260 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024261 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24262 (ctxt->user_sax->elementDecl != NULL))
24263 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24264}
24265
24266static void
24267notationDeclSplit(void *ctx, const xmlChar *name,
24268 const xmlChar *publicId, const xmlChar *systemId)
24269{
Daniel Veillard971771e2005-07-09 17:32:57 +000024270 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024271 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24272 (ctxt->user_sax->notationDecl != NULL))
24273 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24274 systemId);
24275}
24276
24277static void
24278unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24279 const xmlChar *publicId, const xmlChar *systemId,
24280 const xmlChar *notationName)
24281{
Daniel Veillard971771e2005-07-09 17:32:57 +000024282 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024283 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24284 (ctxt->user_sax->unparsedEntityDecl != NULL))
24285 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24286 systemId, notationName);
24287}
24288
24289static void
24290setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
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->setDocumentLocator != NULL))
24295 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24296}
24297
24298static void
24299startDocumentSplit(void *ctx)
24300{
Daniel Veillard971771e2005-07-09 17:32:57 +000024301 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024302 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24303 (ctxt->user_sax->startDocument != NULL))
24304 ctxt->user_sax->startDocument(ctxt->user_data);
24305}
24306
24307static void
24308endDocumentSplit(void *ctx)
24309{
Daniel Veillard971771e2005-07-09 17:32:57 +000024310 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024311 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24312 (ctxt->user_sax->endDocument != NULL))
24313 ctxt->user_sax->endDocument(ctxt->user_data);
24314}
24315
24316static void
24317processingInstructionSplit(void *ctx, const xmlChar *target,
24318 const xmlChar *data)
24319{
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->processingInstruction != NULL))
24323 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24324}
24325
24326static void
24327commentSplit(void *ctx, const xmlChar *value)
24328{
Daniel Veillard971771e2005-07-09 17:32:57 +000024329 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024330 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24331 (ctxt->user_sax->comment != NULL))
24332 ctxt->user_sax->comment(ctxt->user_data, value);
24333}
24334
24335/*
24336 * Varargs error callbacks to the user application, harder ...
24337 */
24338
Daniel Veillardffa3c742005-07-21 13:24:09 +000024339static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024340warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024341 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024342 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24343 (ctxt->user_sax->warning != NULL)) {
24344 TODO
24345 }
24346}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024347static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024348errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024349 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024350 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24351 (ctxt->user_sax->error != NULL)) {
24352 TODO
24353 }
24354}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024355static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024356fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024357 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024358 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24359 (ctxt->user_sax->fatalError != NULL)) {
24360 TODO
24361 }
24362}
24363
24364/*
24365 * Those are function where both the user handler and the schemas handler
24366 * need to be called.
24367 */
24368static void
24369charactersSplit(void *ctx, const xmlChar *ch, int len)
24370{
Daniel Veillard971771e2005-07-09 17:32:57 +000024371 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024372 if (ctxt == NULL)
24373 return;
24374 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24375 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24376 if (ctxt->ctxt != NULL)
24377 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24378}
24379
24380static void
24381ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24382{
Daniel Veillard971771e2005-07-09 17:32:57 +000024383 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024384 if (ctxt == NULL)
24385 return;
24386 if ((ctxt->user_sax != NULL) &&
24387 (ctxt->user_sax->ignorableWhitespace != NULL))
24388 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24389 if (ctxt->ctxt != NULL)
24390 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24391}
24392
24393static void
24394cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24395{
Daniel Veillard971771e2005-07-09 17:32:57 +000024396 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024397 if (ctxt == NULL)
24398 return;
24399 if ((ctxt->user_sax != NULL) &&
24400 (ctxt->user_sax->ignorableWhitespace != NULL))
24401 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24402 if (ctxt->ctxt != NULL)
24403 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24404}
24405
24406static void
24407referenceSplit(void *ctx, const xmlChar *name)
24408{
Daniel Veillard971771e2005-07-09 17:32:57 +000024409 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024410 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24411 (ctxt->user_sax->reference != NULL))
24412 ctxt->user_sax->reference(ctxt->user_data, name);
24413 if (ctxt->ctxt != NULL)
24414 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24415}
24416
24417static void
24418startElementNsSplit(void *ctx, const xmlChar * localname,
24419 const xmlChar * prefix, const xmlChar * URI,
24420 int nb_namespaces, const xmlChar ** namespaces,
24421 int nb_attributes, int nb_defaulted,
24422 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024423 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024424 if (ctxt == NULL)
24425 return;
24426 if ((ctxt->user_sax != NULL) &&
24427 (ctxt->user_sax->startElementNs != NULL))
24428 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24429 URI, nb_namespaces, namespaces,
24430 nb_attributes, nb_defaulted,
24431 attributes);
24432 if (ctxt->ctxt != NULL)
24433 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24434 URI, nb_namespaces, namespaces,
24435 nb_attributes, nb_defaulted,
24436 attributes);
24437}
24438
24439static void
24440endElementNsSplit(void *ctx, const xmlChar * localname,
24441 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024442 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024443 if (ctxt == NULL)
24444 return;
24445 if ((ctxt->user_sax != NULL) &&
24446 (ctxt->user_sax->endElementNs != NULL))
24447 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24448 if (ctxt->ctxt != NULL)
24449 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24450}
24451
Daniel Veillard4255d502002-04-16 15:50:10 +000024452/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024453 * xmlSchemaSAXPlug:
24454 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024455 * @sax: a pointer to the original xmlSAXHandlerPtr
24456 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024457 *
24458 * Plug a SAX based validation layer in a SAX parsing event flow.
24459 * The original @saxptr and @dataptr data are replaced by new pointers
24460 * but the calls to the original will be maintained.
24461 *
24462 * Returns a pointer to a data structure needed to unplug the validation layer
24463 * or NULL in case of errors.
24464 */
24465xmlSchemaSAXPlugPtr
24466xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24467 xmlSAXHandlerPtr *sax, void **user_data)
24468{
24469 xmlSchemaSAXPlugPtr ret;
24470 xmlSAXHandlerPtr old_sax;
24471
24472 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24473 return(NULL);
24474
24475 /*
24476 * We only allow to plug into SAX2 event streams
24477 */
24478 old_sax = *sax;
24479 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24480 return(NULL);
24481 if ((old_sax != NULL) &&
24482 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24483 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24484 return(NULL);
24485
24486 /*
24487 * everything seems right allocate the local data needed for that layer
24488 */
24489 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24490 if (ret == NULL) {
24491 return(NULL);
24492 }
24493 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24494 ret->magic = XML_SAX_PLUG_MAGIC;
24495 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24496 ret->ctxt = ctxt;
24497 ret->user_sax_ptr = sax;
24498 ret->user_sax = old_sax;
24499 if (old_sax == NULL) {
24500 /*
24501 * go direct, no need for the split block and functions.
24502 */
24503 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24504 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24505 /*
24506 * Note that we use the same text-function for both, to prevent
24507 * the parser from testing for ignorable whitespace.
24508 */
24509 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24510 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24511
24512 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24513 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24514
24515 ret->user_data = ctxt;
24516 *user_data = ctxt;
24517 } else {
24518 /*
24519 * for each callback unused by Schemas initialize it to the Split
24520 * routine only if non NULL in the user block, this can speed up
24521 * things at the SAX level.
24522 */
24523 if (old_sax->internalSubset != NULL)
24524 ret->schemas_sax.internalSubset = internalSubsetSplit;
24525 if (old_sax->isStandalone != NULL)
24526 ret->schemas_sax.isStandalone = isStandaloneSplit;
24527 if (old_sax->hasInternalSubset != NULL)
24528 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24529 if (old_sax->hasExternalSubset != NULL)
24530 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24531 if (old_sax->resolveEntity != NULL)
24532 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24533 if (old_sax->getEntity != NULL)
24534 ret->schemas_sax.getEntity = getEntitySplit;
24535 if (old_sax->entityDecl != NULL)
24536 ret->schemas_sax.entityDecl = entityDeclSplit;
24537 if (old_sax->notationDecl != NULL)
24538 ret->schemas_sax.notationDecl = notationDeclSplit;
24539 if (old_sax->attributeDecl != NULL)
24540 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24541 if (old_sax->elementDecl != NULL)
24542 ret->schemas_sax.elementDecl = elementDeclSplit;
24543 if (old_sax->unparsedEntityDecl != NULL)
24544 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24545 if (old_sax->setDocumentLocator != NULL)
24546 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24547 if (old_sax->startDocument != NULL)
24548 ret->schemas_sax.startDocument = startDocumentSplit;
24549 if (old_sax->endDocument != NULL)
24550 ret->schemas_sax.endDocument = endDocumentSplit;
24551 if (old_sax->processingInstruction != NULL)
24552 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24553 if (old_sax->comment != NULL)
24554 ret->schemas_sax.comment = commentSplit;
24555 if (old_sax->warning != NULL)
24556 ret->schemas_sax.warning = warningSplit;
24557 if (old_sax->error != NULL)
24558 ret->schemas_sax.error = errorSplit;
24559 if (old_sax->fatalError != NULL)
24560 ret->schemas_sax.fatalError = fatalErrorSplit;
24561 if (old_sax->getParameterEntity != NULL)
24562 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24563 if (old_sax->externalSubset != NULL)
24564 ret->schemas_sax.externalSubset = externalSubsetSplit;
24565
24566 /*
24567 * the 6 schemas callback have to go to the splitter functions
24568 * Note that we use the same text-function for ignorableWhitespace
24569 * if possible, to prevent the parser from testing for ignorable
24570 * whitespace.
24571 */
24572 ret->schemas_sax.characters = charactersSplit;
24573 if ((old_sax->ignorableWhitespace != NULL) &&
24574 (old_sax->ignorableWhitespace != old_sax->characters))
24575 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24576 else
24577 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24578 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24579 ret->schemas_sax.reference = referenceSplit;
24580 ret->schemas_sax.startElementNs = startElementNsSplit;
24581 ret->schemas_sax.endElementNs = endElementNsSplit;
24582
24583 ret->user_data_ptr = user_data;
24584 ret->user_data = *user_data;
24585 *user_data = ret;
24586 }
24587
24588 /*
24589 * plug the pointers back.
24590 */
24591 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024592 ctxt->sax = *sax;
24593 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24594 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024595 return(ret);
24596}
24597
24598/**
24599 * xmlSchemaSAXUnplug:
24600 * @plug: a data structure returned by xmlSchemaSAXPlug
24601 *
24602 * Unplug a SAX based validation layer in a SAX parsing event flow.
24603 * The original pointers used in the call are restored.
24604 *
24605 * Returns 0 in case of success and -1 in case of failure.
24606 */
24607int
24608xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24609{
24610 xmlSAXHandlerPtr *sax;
24611 void **user_data;
24612
24613 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24614 return(-1);
24615 plug->magic = 0;
24616
Daniel Veillardf10ae122005-07-10 19:03:16 +000024617 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024618 /* restore the data */
24619 sax = plug->user_sax_ptr;
24620 *sax = plug->user_sax;
24621 if (plug->user_sax != NULL) {
24622 user_data = plug->user_data_ptr;
24623 *user_data = plug->user_data;
24624 }
24625
24626 /* free and return */
24627 xmlFree(plug);
24628 return(0);
24629}
24630
24631/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024632 * xmlSchemaValidateStream:
24633 * @ctxt: a schema validation context
24634 * @input: the input to use for reading the data
24635 * @enc: an optional encoding information
24636 * @sax: a SAX handler for the resulting events
24637 * @user_data: the context to provide to the SAX handler.
24638 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024639 * Validate an input based on a flow of SAX event from the parser
24640 * and forward the events to the @sax handler with the provided @user_data
24641 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024642 *
24643 * Returns 0 if the document is schemas valid, a positive error code
24644 * number otherwise and -1 in case of internal or API error.
24645 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024646int
Daniel Veillard4255d502002-04-16 15:50:10 +000024647xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024648 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24649 xmlSAXHandlerPtr sax, void *user_data)
24650{
Daniel Veillard971771e2005-07-09 17:32:57 +000024651 xmlSchemaSAXPlugPtr plug = NULL;
24652 xmlSAXHandlerPtr old_sax = NULL;
24653 xmlParserCtxtPtr pctxt = NULL;
24654 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024655 int ret;
24656
Daniel Veillard4255d502002-04-16 15:50:10 +000024657 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024658 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024659
Daniel Veillardcdc82732005-07-08 15:04:06 +000024660 /*
24661 * prepare the parser
24662 */
24663 pctxt = xmlNewParserCtxt();
24664 if (pctxt == NULL)
24665 return (-1);
24666 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000024667 pctxt->sax = sax;
24668 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024669#if 0
24670 if (options)
24671 xmlCtxtUseOptions(pctxt, options);
24672#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024673 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024674
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024675 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024676 if (inputStream == NULL) {
24677 ret = -1;
24678 goto done;
24679 }
24680 inputPush(pctxt, inputStream);
24681 ctxt->parserCtxt = pctxt;
24682 ctxt->input = input;
24683
24684 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000024685 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000024686 */
Daniel Veillard971771e2005-07-09 17:32:57 +000024687 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
24688 if (plug == NULL) {
24689 ret = -1;
24690 goto done;
24691 }
24692 ctxt->input = input;
24693 ctxt->enc = enc;
24694 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024695 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24696 ret = xmlSchemaVStart(ctxt);
24697
24698 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24699 ret = ctxt->parserCtxt->errNo;
24700 if (ret == 0)
24701 ret = 1;
24702 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024703
24704done:
Daniel Veillard971771e2005-07-09 17:32:57 +000024705 ctxt->parserCtxt = NULL;
24706 ctxt->sax = NULL;
24707 ctxt->input = NULL;
24708 if (plug != NULL) {
24709 xmlSchemaSAXUnplug(plug);
24710 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024711 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000024712 if (pctxt != NULL) {
24713 pctxt->sax = old_sax;
24714 xmlFreeParserCtxt(pctxt);
24715 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024716 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024717}
24718
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024719/**
24720 * xmlSchemaValidateFile:
24721 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024722 * @filename: the URI of the instance
24723 * @options: a future set of options, currently unused
24724 *
24725 * Do a schemas validation of the given resource, it will use the
24726 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024727 *
24728 * Returns 0 if the document is valid, a positive error code
24729 * number otherwise and -1 in case of an internal or API error.
24730 */
24731int
24732xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024733 const char * filename,
24734 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024735{
Daniel Veillard81562d22005-06-15 13:27:56 +000024736#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024737 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024738 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024739
24740 if ((ctxt == NULL) || (filename == NULL))
24741 return (-1);
24742
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024743 input = xmlParserInputBufferCreateFilename(filename,
24744 XML_CHAR_ENCODING_NONE);
24745 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024746 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024747 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24748 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024749 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024750#else
24751 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024752#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024753}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024754
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024755#define bottom_xmlschemas
24756#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024757#endif /* LIBXML_SCHEMAS_ENABLED */