blob: 444c0de9528bf2ec1d21718610791198c52c5064 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000069#define DUMP_CONTENT_MODEL
70
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000071#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000104 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000105static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000107#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000108static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000109 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000110#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111
Daniel Veillard4255d502002-04-16 15:50:10 +0000112#define IS_SCHEMA(node, type) \
113 ((node != NULL) && (node->ns != NULL) && \
114 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
115 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
116
Daniel Veillardc0826a72004-08-10 14:17:33 +0000117#define FREE_AND_NULL(str) \
118 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000119 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120 str = NULL; \
121 }
122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000123#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000124 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
125 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000126
127#define IS_COMPLEX_TYPE(item) \
128 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
129 (item->builtInType == XML_SCHEMAS_ANYTYPE))
130
131#define IS_SIMPLE_TYPE(item) \
132 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
133 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000134 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000136#define IS_ANY_SIMPLE_TYPE(item) \
137 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000138 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000139
140#define IS_NOT_TYPEFIXED(item) \
141 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
142 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
143
144#define HAS_COMPLEX_CONTENT(item) \
145 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
146 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
147 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
148
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000149#define HAS_SIMPLE_CONTENT(item) \
150 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
151 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
152
153#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
154
155#define IS_PARTICLE_EMPTIABLE(item) \
156 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000158#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000160#define GET_LIST_ITEM_TYPE(item) item->subtypes
161
162#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
163#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
164#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000166#define IS_MODEL_GROUP(item) \
167 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
168 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
169 (item->type == XML_SCHEMA_TYPE_ALL))
170
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000171#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
172
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000173#define ELEM_TYPE(item) item->subtypes
174
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000175#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000177#define SUBST_GROUP_AFF(item) item->refDecl
178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000179#if 0
180#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
181#endif
182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000183#define SUBSET_RESTRICTION 1<<0
184#define SUBSET_EXTENSION 1<<1
185#define SUBSET_SUBSTITUTION 1<<2
186#define SUBSET_LIST 1<<3
187#define SUBSET_UNION 1<<4
188
Daniel Veillard4255d502002-04-16 15:50:10 +0000189#define XML_SCHEMAS_PARSE_ERROR 1
190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000193typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
194typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000199
200typedef struct _xmlSchemaItemList xmlSchemaItemList;
201typedef xmlSchemaItemList *xmlSchemaItemListPtr;
202
203struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000204 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 int nbItems; /* used for dynamic addition of schemata */
206 int sizeItems; /* used for dynamic addition of schemata */
207};
208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000209typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
210typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
211struct _xmlSchemaAbstractCtxt {
212 int type;
213};
214
215#define XML_SCHEMA_CTXT_PARSER 1
216#define XML_SCHEMA_CTXT_VALIDATOR 2
217
Daniel Veillard4255d502002-04-16 15:50:10 +0000218struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000219 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 void *userData; /* user specific data block */
221 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
222 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000223 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000227 xmlSchemaPtr topschema; /* The main schema */
228 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000231 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 int counter;
233
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000234 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000236 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 const char *buffer;
239 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241 /*
242 * Used to build complex element content models
243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245 xmlAutomataStatePtr start;
246 xmlAutomataStatePtr end;
247 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000248
249 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000250 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000251 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
252 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 xmlSchemaAssemblePtr assemble;
254 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000256 const xmlChar **localImports; /* list of locally imported namespaces */
257 int sizeLocalImports;
258 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000259 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000260 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000261};
262
Daniel Veillard4255d502002-04-16 15:50:10 +0000263#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000267#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
269#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000270#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000271#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
273#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
274#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
275#define XML_SCHEMAS_ATTR_WILD_SKIP 13
276#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
277#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
278#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
279#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281/**
282 * xmlSchemaBasicItem:
283 *
284 * The abstract base type for schema components.
285 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000286typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
287typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
288struct _xmlSchemaBasicItem {
289 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000290};
291
292/**
293 * xmlSchemaAnnotItem:
294 *
295 * The abstract base type for annotated schema components.
296 * (Extends xmlSchemaBasicItem)
297 */
298typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
299typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
300struct _xmlSchemaAnnotItem {
301 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000302 xmlSchemaAnnotPtr annot;
303};
304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000305/**
306 * xmlSchemaTreeItem:
307 *
308 * The abstract base type for tree-like structured schema components.
309 * (Extends xmlSchemaAnnotItem)
310 */
311typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
312typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
313struct _xmlSchemaTreeItem {
314 xmlSchemaTypeType type;
315 xmlSchemaAnnotPtr annot;
316 xmlSchemaTreeItemPtr next;
317 xmlSchemaTreeItemPtr children;
318};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000320/**
321 * xmlSchemaQNameRef:
322 *
323 * A component reference item (not a schema component)
324 * (Extends xmlSchemaBasicItem)
325 */
326typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
327typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
328struct _xmlSchemaQNameRef {
329 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000331 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000332 const xmlChar *name;
333 const xmlChar *targetNamespace;
334};
335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000336/**
337 * xmlSchemaParticle:
338 *
339 * A particle component.
340 * (Extends xmlSchemaTreeItem)
341 */
342typedef struct _xmlSchemaParticle xmlSchemaParticle;
343typedef xmlSchemaParticle *xmlSchemaParticlePtr;
344struct _xmlSchemaParticle {
345 xmlSchemaTypeType type;
346 xmlSchemaAnnotPtr annot;
347 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
348 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
349 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000350 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351 xmlNodePtr node;
352};
353
354/**
355 * xmlSchemaModelGroup:
356 *
357 * A model group component.
358 * (Extends xmlSchemaTreeItem)
359 */
360typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next; /* not used */
366 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
367 xmlNodePtr node;
368};
369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000370#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000371/**
372 * xmlSchemaModelGroupDef:
373 *
374 * A model group definition component.
375 * (Extends xmlSchemaTreeItem)
376 */
377typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
378typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
379struct _xmlSchemaModelGroupDef {
380 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
381 xmlSchemaAnnotPtr annot;
382 xmlSchemaTreeItemPtr next; /* not used */
383 xmlSchemaTreeItemPtr children; /* the "model group" */
384 const xmlChar *name;
385 const xmlChar *targetNamespace;
386 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000387 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388};
389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390typedef struct _xmlSchemaIDC xmlSchemaIDC;
391typedef xmlSchemaIDC *xmlSchemaIDCPtr;
392
393/**
394 * xmlSchemaIDCSelect:
395 *
396 * The identity-constraint "field" and "selector" item, holding the
397 * XPath expression.
398 */
399typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
400typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000401struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402 xmlSchemaIDCSelectPtr next;
403 xmlSchemaIDCPtr idc;
404 int index; /* an index position if significant for IDC key-sequences */
405 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000406 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000407};
408
409/**
410 * xmlSchemaIDC:
411 *
412 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000413 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000414 */
415
416struct _xmlSchemaIDC {
417 xmlSchemaTypeType type;
418 xmlSchemaAnnotPtr annot;
419 xmlSchemaIDCPtr next;
420 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 const xmlChar *targetNamespace;
423 xmlSchemaIDCSelectPtr selector;
424 xmlSchemaIDCSelectPtr fields;
425 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000426 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000427};
428
429/**
430 * xmlSchemaIDCAug:
431 *
432 * The augmented IDC information used for validation.
433 */
434typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
435typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
436struct _xmlSchemaIDCAug {
437 xmlSchemaIDCAugPtr next; /* next in a list */
438 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000439 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000440 tables need to be bubbled upwards */
441};
442
443/**
444 * xmlSchemaPSVIIDCKeySequence:
445 *
446 * The key sequence of a node table item.
447 */
448typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
449typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
450struct _xmlSchemaPSVIIDCKey {
451 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000452 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453};
454
455/**
456 * xmlSchemaPSVIIDCNode:
457 *
458 * The node table item of a node table.
459 */
460typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
461typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
462struct _xmlSchemaPSVIIDCNode {
463 xmlNodePtr node;
464 xmlSchemaPSVIIDCKeyPtr *keys;
465};
466
467/**
468 * xmlSchemaPSVIIDCBinding:
469 *
470 * The identity-constraint binding item of the [identity-constraint table].
471 */
472typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
473typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
474struct _xmlSchemaPSVIIDCBinding {
475 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
476 xmlSchemaIDCPtr definition; /* the IDC definition */
477 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
478 int nbNodes; /* number of entries in the node table */
479 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000480 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 table */
482 /* int nbKeys; number of keys in each key-sequence */
483};
484
485#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
486#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
487
488#define XPATH_STATE_OBJ_MATCHES -2
489#define XPATH_STATE_OBJ_BLOCKED -3
490
491typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
492typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
493
494/**
495 * xmlSchemaIDCStateObj:
496 *
497 * The state object used to evaluate XPath expressions.
498 */
499typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
500typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
501struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000502 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000504 int depth; /* depth of creation */
505 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 int nbHistory;
507 int sizeHistory;
508 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
509 matcher */
510 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000511 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000512};
513
514#define IDC_MATCHER 0
515
516/**
517 * xmlSchemaIDCMatcher:
518 *
519 * Used to IDC selectors (and fields) successively.
520 */
521struct _xmlSchemaIDCMatcher {
522 int type;
523 int depth; /* the tree depth at creation time */
524 xmlSchemaIDCMatcherPtr next; /* next in the list */
525 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
526 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
527 elements */
528 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 int targetDepth;
530};
531
532/*
533* Element info flags.
534*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
536#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
537#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
538#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
539
540#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
541#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
542#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
543
544#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
545#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
546#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
547#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548
549/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000550 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 *
552 * Holds information of an element node.
553 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000554struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000557 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 const xmlChar *nsName;
559 const xmlChar *value;
560 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000562 int flags; /* combination of node info flags */
563 int valNeeded;
564 int normVal;
565
566 xmlSchemaElementPtr decl; /* the element/attribute declaration */
567 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
569 for the scope element*/
570 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
571 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000572 xmlRegExecCtxtPtr regexCtxt;
573
574 const xmlChar **nsBindings; /* Namespace bindings on this element */
575 int nbNsBindings;
576 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000577};
578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000579/*
580* @metaType values of xmlSchemaAttrInfo.
581*/
582#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
584#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
585#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
586#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
589typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
590struct _xmlSchemaAttrInfo {
591 xmlNodePtr node;
592 int nodeType;
593 const xmlChar *localName;
594 const xmlChar *nsName;
595 const xmlChar *value;
596 xmlSchemaValPtr val; /* the pre-computed value if any */
597 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
598 int flags; /* combination of node info flags */
599
600 xmlSchemaAttributePtr decl; /* the attribute declaration */
601 xmlSchemaAttributePtr use; /* the attribute use */
602 int state;
603 int metaType;
604 const xmlChar *vcValue; /* the value constraint value */
605 xmlSchemaNodeInfoPtr parent;
606};
607
608
609#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000610/**
611 * xmlSchemaValidCtxt:
612 *
613 * A Schemas validation context
614 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000615struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *userData; /* user specific data block */
618 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000619 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000621
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 xmlSchemaPtr schema; /* The schema in use */
623 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 xmlCharEncoding enc;
626 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000627 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000629
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 int err;
631 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000632
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000633 xmlNodePtr node;
634 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000635 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637 xmlRegExecCtxtPtr regexp;
638 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000639
Daniel Veillardc0826a72004-08-10 14:17:33 +0000640 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000641 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000642 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000643 xmlSchemaParserCtxtPtr pctxt;
644 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000647 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000649 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
652
653 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
654 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000655
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
657 int nbIdcNodes;
658 int sizeIdcNodes;
659
660 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
661 int nbIdcKeys;
662 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000663
664 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000665
666 xmlDictPtr dict;
667
Daniel Veillard39e5c892005-07-03 22:48:50 +0000668#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000670#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671
672 xmlSchemaAttrInfoPtr *attrInfos;
673 int nbAttrInfos;
674 int sizeAttrInfos;
675
676 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000677};
678
Daniel Veillard1d913862003-11-21 00:28:39 +0000679/*
680 * These are the entries in the schemas importSchemas hash table
681 */
682typedef struct _xmlSchemaImport xmlSchemaImport;
683typedef xmlSchemaImport *xmlSchemaImportPtr;
684struct _xmlSchemaImport {
685 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000686 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000687 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000688 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000689};
Daniel Veillard4255d502002-04-16 15:50:10 +0000690
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000691/*
692 * These are the entries associated to includes in a schemas
693 */
694typedef struct _xmlSchemaInclude xmlSchemaInclude;
695typedef xmlSchemaInclude *xmlSchemaIncludePtr;
696struct _xmlSchemaInclude {
697 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698 const xmlChar *schemaLocation;
699 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000700 const xmlChar *origTargetNamespace;
701 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000702};
703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000704/**
705 * xmlSchemaSubstGroup:
706 *
707 *
708 */
709typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
710typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
711struct _xmlSchemaSubstGroup {
712 xmlSchemaElementPtr head;
713 xmlSchemaItemListPtr members;
714};
715
Daniel Veillard4255d502002-04-16 15:50:10 +0000716/************************************************************************
717 * *
718 * Some predeclarations *
719 * *
720 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000722static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
723 xmlSchemaPtr schema,
724 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725static void
726xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
727 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000728static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000729xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
730static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000731xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
732 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000733static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000734xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
735 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000736static void
737xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000738static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000739xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740static xmlSchemaTreeItemPtr
741xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
742 xmlNodePtr node, xmlSchemaTypeType type,
743 int withParticle);
744static const xmlChar *
745xmlSchemaCompTypeToString(xmlSchemaTypeType type);
746static xmlSchemaTypeLinkPtr
747xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748static void
749xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
750 const char *funcName,
751 const char *message);
752static int
753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
754 xmlSchemaTypePtr baseType,
755 int subset);
756static void
757xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
758 xmlSchemaParserCtxtPtr ctxt,
759 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000760
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761/************************************************************************
762 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000763 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 * *
765 ************************************************************************/
766
767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000768 * xmlSchemaCompTypeToString:
769 * @type: the type of the schema item
770 *
771 * Returns the component name of a schema item.
772 */
773static const xmlChar *
774xmlSchemaCompTypeToString(xmlSchemaTypeType type)
775{
776 switch (type) {
777 case XML_SCHEMA_TYPE_SIMPLE:
778 return(BAD_CAST "simple type definition");
779 case XML_SCHEMA_TYPE_COMPLEX:
780 return(BAD_CAST "complex type definition");
781 case XML_SCHEMA_TYPE_ELEMENT:
782 return(BAD_CAST "element declaration");
783 case XML_SCHEMA_TYPE_ATTRIBUTE:
784 return(BAD_CAST "attribute declaration");
785 case XML_SCHEMA_TYPE_GROUP:
786 return(BAD_CAST "model group definition");
787 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
788 return(BAD_CAST "attribute group definition");
789 case XML_SCHEMA_TYPE_NOTATION:
790 return(BAD_CAST "notation declaration");
791 case XML_SCHEMA_TYPE_SEQUENCE:
792 return(BAD_CAST "model group (sequence)");
793 case XML_SCHEMA_TYPE_CHOICE:
794 return(BAD_CAST "model group (choice)");
795 case XML_SCHEMA_TYPE_ALL:
796 return(BAD_CAST "model group (all)");
797 case XML_SCHEMA_TYPE_PARTICLE:
798 return(BAD_CAST "particle");
799 default:
800 return(BAD_CAST "Not a schema component");
801 }
802}
803
804/**
805 * xmlSchemaGetComponentNode:
806 * @item: a schema component
807 *
808 * Returns node associated with the schema component.
809 * NOTE that such a node need not be available; plus, a component's
810 * node need not to reflect the component directly, since there is no
811 * one-to-one relationship between the XML Schema representation and
812 * the component representation.
813 */
814static xmlNodePtr
815xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
816{
817 switch (item->type) {
818 case XML_SCHEMA_TYPE_ELEMENT:
819 return (((xmlSchemaElementPtr) item)->node);
820 case XML_SCHEMA_TYPE_ATTRIBUTE:
821 return (((xmlSchemaAttributePtr) item)->node);
822 case XML_SCHEMA_TYPE_COMPLEX:
823 case XML_SCHEMA_TYPE_SIMPLE:
824 return (((xmlSchemaTypePtr) item)->node);
825 case XML_SCHEMA_TYPE_ANY:
826 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
827 return (((xmlSchemaWildcardPtr) item)->node);
828 case XML_SCHEMA_TYPE_PARTICLE:
829 return (((xmlSchemaParticlePtr) item)->node);
830 case XML_SCHEMA_TYPE_SEQUENCE:
831 case XML_SCHEMA_TYPE_CHOICE:
832 case XML_SCHEMA_TYPE_ALL:
833 return (((xmlSchemaModelGroupPtr) item)->node);
834 case XML_SCHEMA_TYPE_GROUP:
835 return (((xmlSchemaModelGroupDefPtr) item)->node);
836 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
837 return (((xmlSchemaAttributeGroupPtr) item)->node);
838 case XML_SCHEMA_TYPE_IDC_UNIQUE:
839 case XML_SCHEMA_TYPE_IDC_KEY:
840 case XML_SCHEMA_TYPE_IDC_KEYREF:
841 return (((xmlSchemaIDCPtr) item)->node);
842 default:
843 return (NULL);
844 }
845}
846
847#if 0
848/**
849 * xmlSchemaGetNextComponent:
850 * @item: a schema component
851 *
852 * Returns the next sibling of the schema component.
853 */
854static xmlSchemaBasicItemPtr
855xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
856{
857 switch (item->type) {
858 case XML_SCHEMA_TYPE_ELEMENT:
859 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
860 case XML_SCHEMA_TYPE_ATTRIBUTE:
861 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
862 case XML_SCHEMA_TYPE_COMPLEX:
863 case XML_SCHEMA_TYPE_SIMPLE:
864 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
865 case XML_SCHEMA_TYPE_ANY:
866 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
867 return (NULL);
868 case XML_SCHEMA_TYPE_PARTICLE:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
870 case XML_SCHEMA_TYPE_SEQUENCE:
871 case XML_SCHEMA_TYPE_CHOICE:
872 case XML_SCHEMA_TYPE_ALL:
873 return (NULL);
874 case XML_SCHEMA_TYPE_GROUP:
875 return (NULL);
876 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
877 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
878 case XML_SCHEMA_TYPE_IDC_UNIQUE:
879 case XML_SCHEMA_TYPE_IDC_KEY:
880 case XML_SCHEMA_TYPE_IDC_KEYREF:
881 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
882 default:
883 return (NULL);
884 }
885}
886#endif
887
888/**
889 * xmlSchemaGetAttrName:
890 * @attr: the attribute declaration/use
891 *
892 * Returns the name of the attribute; if the attribute
893 * is a reference, the name of the referenced global type will be returned.
894 */
895static const xmlChar *
896xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
897{
898 if (attr->ref != NULL)
899 return(attr->ref);
900 else
901 return(attr->name);
902}
903
904/**
905 * xmlSchemaGetAttrTargetNsURI:
906 * @type: the type (element or attribute)
907 *
908 * Returns the target namespace URI of the type; if the type is a reference,
909 * the target namespace of the referenced type will be returned.
910 */
911static const xmlChar *
912xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
913{
914 if (attr->ref != NULL)
915 return (attr->refNs);
916 else
917 return(attr->targetNamespace);
918}
919
920/**
921 * xmlSchemaFormatQName:
922 * @buf: the string buffer
923 * @namespaceName: the namespace name
924 * @localName: the local name
925 *
926 * Returns the given QName in the format "{namespaceName}localName" or
927 * just "localName" if @namespaceName is NULL.
928 *
929 * Returns the localName if @namespaceName is NULL, a formatted
930 * string otherwise.
931 */
932static const xmlChar*
933xmlSchemaFormatQName(xmlChar **buf,
934 const xmlChar *namespaceName,
935 const xmlChar *localName)
936{
937 FREE_AND_NULL(*buf)
938 if (namespaceName == NULL)
939 return(localName);
940
941 *buf = xmlStrdup(BAD_CAST "{");
942 *buf = xmlStrcat(*buf, namespaceName);
943 *buf = xmlStrcat(*buf, BAD_CAST "}");
944 *buf = xmlStrcat(*buf, localName);
945
946 return ((const xmlChar *) *buf);
947}
948
949static const xmlChar*
950xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
951{
952 if (ns != NULL)
953 return (xmlSchemaFormatQName(buf, ns->href, localName));
954 else
955 return (xmlSchemaFormatQName(buf, NULL, localName));
956}
957
958static const xmlChar *
959xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
960{
961 switch (item->type) {
962 case XML_SCHEMA_TYPE_ELEMENT:
963 return (((xmlSchemaElementPtr) item)->name);
964 case XML_SCHEMA_TYPE_ATTRIBUTE:
965 return (((xmlSchemaAttributePtr) item)->name);
966 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
967 return (((xmlSchemaAttributeGroupPtr) item)->name);
968 case XML_SCHEMA_TYPE_BASIC:
969 case XML_SCHEMA_TYPE_SIMPLE:
970 case XML_SCHEMA_TYPE_COMPLEX:
971 return (((xmlSchemaTypePtr) item)->name);
972 case XML_SCHEMA_TYPE_GROUP:
973 return (((xmlSchemaModelGroupDefPtr) item)->name);
974 case XML_SCHEMA_TYPE_IDC_KEY:
975 case XML_SCHEMA_TYPE_IDC_UNIQUE:
976 case XML_SCHEMA_TYPE_IDC_KEYREF:
977 return (((xmlSchemaIDCPtr) item)->name);
978 default:
979 /*
980 * Other components cannot have names.
981 */
982 break;
983 }
984 return (NULL);
985}
986
987static const xmlChar *
988xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
989{
990 switch (item->type) {
991 case XML_SCHEMA_TYPE_ELEMENT:
992 return (((xmlSchemaElementPtr) item)->targetNamespace);
993 case XML_SCHEMA_TYPE_ATTRIBUTE:
994 return (((xmlSchemaAttributePtr) item)->targetNamespace);
995 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
996 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
997 case XML_SCHEMA_TYPE_BASIC:
998 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
999 case XML_SCHEMA_TYPE_SIMPLE:
1000 case XML_SCHEMA_TYPE_COMPLEX:
1001 return (((xmlSchemaTypePtr) item)->targetNamespace);
1002 case XML_SCHEMA_TYPE_GROUP:
1003 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1004 case XML_SCHEMA_TYPE_IDC_KEY:
1005 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1006 case XML_SCHEMA_TYPE_IDC_KEYREF:
1007 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1008 default:
1009 /*
1010 * Other components cannot have names.
1011 */
1012 break;
1013 }
1014 return (NULL);
1015}
1016
1017static const xmlChar*
1018xmlSchemaGetComponentQName(xmlChar **buf,
1019 void *item)
1020{
1021 return (xmlSchemaFormatQName(buf,
1022 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1023 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1024}
1025
1026/**
1027 * xmlSchemaWildcardPCToString:
1028 * @pc: the type of processContents
1029 *
1030 * Returns a string representation of the type of
1031 * processContents.
1032 */
1033static const xmlChar *
1034xmlSchemaWildcardPCToString(int pc)
1035{
1036 switch (pc) {
1037 case XML_SCHEMAS_ANY_SKIP:
1038 return (BAD_CAST "skip");
1039 case XML_SCHEMAS_ANY_LAX:
1040 return (BAD_CAST "lax");
1041 case XML_SCHEMAS_ANY_STRICT:
1042 return (BAD_CAST "strict");
1043 default:
1044 return (BAD_CAST "invalid process contents");
1045 }
1046}
1047
1048/**
1049 * xmlSchemaGetCanonValueWhtspExt:
1050 * @val: the precomputed value
1051 * @retValue: the returned value
1052 * @ws: the whitespace type of the value
1053 *
1054 * Get a the cononical representation of the value.
1055 * The caller has to free the returned retValue.
1056 *
1057 * Returns 0 if the value could be built and -1 in case of
1058 * API errors or if the value type is not supported yet.
1059 */
1060static int
1061xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1062 xmlSchemaWhitespaceValueType ws,
1063 xmlChar **retValue)
1064{
1065 int list;
1066 xmlSchemaValType valType;
1067 const xmlChar *value, *value2 = NULL;
1068
1069
1070 if ((retValue == NULL) || (val == NULL))
1071 return (-1);
1072 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1073 *retValue = NULL;
1074 do {
1075 value = NULL;
1076 valType = xmlSchemaGetValType(val);
1077 switch (valType) {
1078 case XML_SCHEMAS_STRING:
1079 case XML_SCHEMAS_NORMSTRING:
1080 case XML_SCHEMAS_ANYSIMPLETYPE:
1081 value = xmlSchemaValueGetAsString(val);
1082 if (value != NULL) {
1083 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1084 value2 = xmlSchemaCollapseString(value);
1085 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1086 value2 = xmlSchemaWhiteSpaceReplace(value);
1087 if (value2 != NULL)
1088 value = value2;
1089 }
1090 break;
1091 default:
1092 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1093 if (value2 != NULL)
1094 xmlFree((xmlChar *) value2);
1095 goto internal_error;
1096 }
1097 value = value2;
1098 }
1099 if (*retValue == NULL)
1100 if (value == NULL) {
1101 if (! list)
1102 *retValue = xmlStrdup(BAD_CAST "");
1103 } else
1104 *retValue = xmlStrdup(value);
1105 else if (value != NULL) {
1106 /* List. */
1107 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1108 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1109 }
1110 FREE_AND_NULL(value2)
1111 val = xmlSchemaValueGetNext(val);
1112 } while (val != NULL);
1113
1114 return (0);
1115internal_error:
1116 if (*retValue != NULL)
1117 xmlFree((xmlChar *) (*retValue));
1118 if (value2 != NULL)
1119 xmlFree((xmlChar *) value2);
1120 return (-1);
1121}
1122
1123/**
1124 * xmlSchemaFormatItemForReport:
1125 * @buf: the string buffer
1126 * @itemDes: the designation of the item
1127 * @itemName: the name of the item
1128 * @item: the item as an object
1129 * @itemNode: the node of the item
1130 * @local: the local name
1131 * @parsing: if the function is used during the parse
1132 *
1133 * Returns a representation of the given item used
1134 * for error reports.
1135 *
1136 * The following order is used to build the resulting
1137 * designation if the arguments are not NULL:
1138 * 1a. If itemDes not NULL -> itemDes
1139 * 1b. If (itemDes not NULL) and (itemName not NULL)
1140 * -> itemDes + itemName
1141 * 2. If the preceding was NULL and (item not NULL) -> item
1142 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1143 *
1144 * If the itemNode is an attribute node, the name of the attribute
1145 * will be appended to the result.
1146 *
1147 * Returns the formatted string and sets @buf to the resulting value.
1148 */
1149static xmlChar*
1150xmlSchemaFormatItemForReport(xmlChar **buf,
1151 const xmlChar *itemDes,
1152 xmlSchemaTypePtr item,
1153 xmlNodePtr itemNode)
1154{
1155 xmlChar *str = NULL;
1156 int named = 1;
1157
1158 if (*buf != NULL) {
1159 xmlFree(*buf);
1160 *buf = NULL;
1161 }
1162
1163 if (itemDes != NULL) {
1164 *buf = xmlStrdup(itemDes);
1165 } else if (item != NULL) {
1166 switch (item->type) {
1167 case XML_SCHEMA_TYPE_BASIC:
1168 if (VARIETY_ATOMIC(item))
1169 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1170 else if (VARIETY_LIST(item))
1171 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1172 else if (VARIETY_UNION(item))
1173 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1174 else
1175 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1176 *buf = xmlStrcat(*buf, item->name);
1177 *buf = xmlStrcat(*buf, BAD_CAST "'");
1178 break;
1179 case XML_SCHEMA_TYPE_SIMPLE:
1180 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1181 *buf = xmlStrdup(BAD_CAST"");
1182 } else {
1183 *buf = xmlStrdup(BAD_CAST "local ");
1184 }
1185 if (VARIETY_ATOMIC(item))
1186 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1187 else if (VARIETY_LIST(item))
1188 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1189 else if (VARIETY_UNION(item))
1190 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1191 else
1192 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1193 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1194 *buf = xmlStrcat(*buf, BAD_CAST " '");
1195 *buf = xmlStrcat(*buf, item->name);
1196 *buf = xmlStrcat(*buf, BAD_CAST "'");
1197 }
1198 break;
1199 case XML_SCHEMA_TYPE_COMPLEX:
1200 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1201 *buf = xmlStrdup(BAD_CAST "");
1202 else
1203 *buf = xmlStrdup(BAD_CAST "local ");
1204 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1205 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1206 *buf = xmlStrcat(*buf, BAD_CAST " '");
1207 *buf = xmlStrcat(*buf, item->name);
1208 *buf = xmlStrcat(*buf, BAD_CAST "'");
1209 }
1210 break;
1211 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1212 xmlSchemaAttributePtr attr;
1213
1214 attr = (xmlSchemaAttributePtr) item;
1215 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1216 (attr->ref == NULL)) {
1217 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1218 *buf = xmlStrcat(*buf, BAD_CAST " '");
1219 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1220 attr->targetNamespace, attr->name));
1221 FREE_AND_NULL(str)
1222 *buf = xmlStrcat(*buf, BAD_CAST "'");
1223 } else {
1224 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1225 *buf = xmlStrcat(*buf, BAD_CAST " '");
1226 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1227 attr->refNs, attr->ref));
1228 FREE_AND_NULL(str)
1229 *buf = xmlStrcat(*buf, BAD_CAST "'");
1230 }
1231 }
1232 break;
1233 case XML_SCHEMA_TYPE_ELEMENT: {
1234 xmlSchemaElementPtr elem;
1235
1236 elem = (xmlSchemaElementPtr) item;
1237 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1238 (elem->ref == NULL)) {
1239 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1240 *buf = xmlStrcat(*buf, BAD_CAST " '");
1241 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1242 elem->targetNamespace, elem->name));
1243 *buf = xmlStrcat(*buf, BAD_CAST "'");
1244 }
1245 }
1246 break;
1247 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1248 case XML_SCHEMA_TYPE_IDC_KEY:
1249 case XML_SCHEMA_TYPE_IDC_KEYREF:
1250 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1251 *buf = xmlStrdup(BAD_CAST "unique '");
1252 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1253 *buf = xmlStrdup(BAD_CAST "key '");
1254 else
1255 *buf = xmlStrdup(BAD_CAST "keyRef '");
1256 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1257 *buf = xmlStrcat(*buf, BAD_CAST "'");
1258 break;
1259 case XML_SCHEMA_TYPE_ANY:
1260 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1261 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1262 ((xmlSchemaWildcardPtr) item)->processContents));
1263 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1264 break;
1265 case XML_SCHEMA_FACET_MININCLUSIVE:
1266 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1267 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1268 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1269 case XML_SCHEMA_FACET_TOTALDIGITS:
1270 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1271 case XML_SCHEMA_FACET_PATTERN:
1272 case XML_SCHEMA_FACET_ENUMERATION:
1273 case XML_SCHEMA_FACET_WHITESPACE:
1274 case XML_SCHEMA_FACET_LENGTH:
1275 case XML_SCHEMA_FACET_MAXLENGTH:
1276 case XML_SCHEMA_FACET_MINLENGTH:
1277 *buf = xmlStrdup(BAD_CAST "facet '");
1278 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1279 *buf = xmlStrcat(*buf, BAD_CAST "'");
1280 break;
1281 case XML_SCHEMA_TYPE_NOTATION:
1282 *buf = xmlStrdup(BAD_CAST "notation");
1283 break;
1284 case XML_SCHEMA_TYPE_GROUP: {
1285 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1286 *buf = xmlStrcat(*buf, BAD_CAST " '");
1287 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1288 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1289 ((xmlSchemaModelGroupDefPtr) item)->name));
1290 *buf = xmlStrcat(*buf, BAD_CAST "'");
1291 FREE_AND_NULL(str)
1292 }
1293 break;
1294 case XML_SCHEMA_TYPE_SEQUENCE:
1295 case XML_SCHEMA_TYPE_CHOICE:
1296 case XML_SCHEMA_TYPE_ALL:
1297 case XML_SCHEMA_TYPE_PARTICLE:
1298 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1299 break;
1300 default:
1301 named = 0;
1302 }
1303 } else
1304 named = 0;
1305
1306 if ((named == 0) && (itemNode != NULL)) {
1307 xmlNodePtr elem;
1308
1309 if (itemNode->type == XML_ATTRIBUTE_NODE)
1310 elem = itemNode->parent;
1311 else
1312 elem = itemNode;
1313 *buf = xmlStrdup(BAD_CAST "Element '");
1314 if (elem->ns != NULL) {
1315 *buf = xmlStrcat(*buf,
1316 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1317 FREE_AND_NULL(str)
1318 } else
1319 *buf = xmlStrcat(*buf, elem->name);
1320 *buf = xmlStrcat(*buf, BAD_CAST "'");
1321
1322 }
1323 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1324 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1325 if (itemNode->ns != NULL) {
1326 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1327 itemNode->ns->href, itemNode->name));
1328 FREE_AND_NULL(str)
1329 } else
1330 *buf = xmlStrcat(*buf, itemNode->name);
1331 *buf = xmlStrcat(*buf, BAD_CAST "'");
1332 }
1333 FREE_AND_NULL(str)
1334
1335 return (*buf);
1336}
1337
1338/**
1339 * xmlSchemaFormatFacetEnumSet:
1340 * @buf: the string buffer
1341 * @type: the type holding the enumeration facets
1342 *
1343 * Builds a string consisting of all enumeration elements.
1344 *
1345 * Returns a string of all enumeration elements.
1346 */
1347static const xmlChar *
1348xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1349 xmlChar **buf, xmlSchemaTypePtr type)
1350{
1351 xmlSchemaFacetPtr facet;
1352 xmlSchemaWhitespaceValueType ws;
1353 xmlChar *value = NULL;
1354 int res;
1355
1356 if (*buf != NULL)
1357 xmlFree(*buf);
1358 *buf = NULL;
1359
1360 do {
1361 /*
1362 * Use the whitespace type of the base type.
1363 */
1364 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1365 for (facet = type->facets; facet != NULL; facet = facet->next) {
1366 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1367 continue;
1368 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1369 ws, &value);
1370 if (res == -1) {
1371 xmlSchemaInternalErr(actxt,
1372 "xmlSchemaFormatFacetEnumSet",
1373 "compute the canonical lexical representation");
1374 if (*buf != NULL)
1375 xmlFree(*buf);
1376 *buf = NULL;
1377 return (NULL);
1378 }
1379 if (*buf == NULL)
1380 *buf = xmlStrdup(BAD_CAST "'");
1381 else
1382 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1383 *buf = xmlStrcat(*buf, BAD_CAST value);
1384 *buf = xmlStrcat(*buf, BAD_CAST "'");
1385 if (value != NULL) {
1386 xmlFree((xmlChar *)value);
1387 value = NULL;
1388 }
1389 }
1390 type = type->baseType;
1391 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1392
1393 return ((const xmlChar *) *buf);
1394}
1395
1396/************************************************************************
1397 * *
1398 * Error functions *
1399 * *
1400 ************************************************************************/
1401
1402#if 0
1403static void
1404xmlSchemaErrMemory(const char *msg)
1405{
1406 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1407 msg);
1408}
1409#endif
1410
1411/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001412 * xmlSchemaPErrMemory:
1413 * @node: a context node
1414 * @extra: extra informations
1415 *
1416 * Handle an out of memory condition
1417 */
1418static void
1419xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1420 const char *extra, xmlNodePtr node)
1421{
1422 if (ctxt != NULL)
1423 ctxt->nberrors++;
1424 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1425 extra);
1426}
1427
1428/**
1429 * xmlSchemaPErr:
1430 * @ctxt: the parsing context
1431 * @node: the context node
1432 * @error: the error code
1433 * @msg: the error message
1434 * @str1: extra data
1435 * @str2: extra data
1436 *
1437 * Handle a parser error
1438 */
1439static void
1440xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1441 const char *msg, const xmlChar * str1, const xmlChar * str2)
1442{
1443 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001444 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001445 void *data = NULL;
1446
1447 if (ctxt != NULL) {
1448 ctxt->nberrors++;
1449 channel = ctxt->error;
1450 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001451 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001453 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 error, XML_ERR_ERROR, NULL, 0,
1455 (const char *) str1, (const char *) str2, NULL, 0, 0,
1456 msg, str1, str2);
1457}
1458
1459/**
1460 * xmlSchemaPErr2:
1461 * @ctxt: the parsing context
1462 * @node: the context node
1463 * @node: the current child
1464 * @error: the error code
1465 * @msg: the error message
1466 * @str1: extra data
1467 * @str2: extra data
1468 *
1469 * Handle a parser error
1470 */
1471static void
1472xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1473 xmlNodePtr child, int error,
1474 const char *msg, const xmlChar * str1, const xmlChar * str2)
1475{
1476 if (child != NULL)
1477 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1478 else
1479 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1480}
1481
Daniel Veillard01fa6152004-06-29 17:04:39 +00001482
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001483/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001484 * xmlSchemaPErrExt:
1485 * @ctxt: the parsing context
1486 * @node: the context node
1487 * @error: the error code
1488 * @strData1: extra data
1489 * @strData2: extra data
1490 * @strData3: extra data
1491 * @msg: the message
1492 * @str1: extra parameter for the message display
1493 * @str2: extra parameter for the message display
1494 * @str3: extra parameter for the message display
1495 * @str4: extra parameter for the message display
1496 * @str5: extra parameter for the message display
1497 *
1498 * Handle a parser error
1499 */
1500static void
1501xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1502 const xmlChar * strData1, const xmlChar * strData2,
1503 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1504 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1505 const xmlChar * str5)
1506{
1507
1508 xmlGenericErrorFunc channel = NULL;
1509 xmlStructuredErrorFunc schannel = NULL;
1510 void *data = NULL;
1511
1512 if (ctxt != NULL) {
1513 ctxt->nberrors++;
1514 channel = ctxt->error;
1515 data = ctxt->userData;
1516 schannel = ctxt->serror;
1517 }
1518 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1519 error, XML_ERR_ERROR, NULL, 0,
1520 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001521 (const char *) strData3, 0, 0, msg, str1, str2,
1522 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001523}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001525/************************************************************************
1526 * *
1527 * Allround error functions *
1528 * *
1529 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001530
1531/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001532 * xmlSchemaVTypeErrMemory:
1533 * @node: a context node
1534 * @extra: extra informations
1535 *
1536 * Handle an out of memory condition
1537 */
1538static void
1539xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1540 const char *extra, xmlNodePtr node)
1541{
1542 if (ctxt != NULL) {
1543 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001544 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001545 }
1546 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1547 extra);
1548}
1549
1550/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001551 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 * @ctxt: the validation context
1553 * @node: the context node
1554 * @error: the error code
1555 * @msg: the error message
1556 * @str1: extra data
1557 * @str2: extra data
1558 * @str3: extra data
1559 *
1560 * Handle a validation error
1561 */
1562static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001563xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1564 int error, xmlNodePtr node, const char *msg,
1565 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001566{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001567 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001568 xmlGenericErrorFunc channel = NULL;
1569 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571 if (ctxt != NULL) {
1572 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1573 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001574 int line = 0;
1575 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001576
1577 vctxt->nberrors++;
1578 vctxt->err = error;
1579 channel = vctxt->error;
1580 schannel = vctxt->serror;
1581 data = vctxt->userData;
1582 if ((node == NULL) && (vctxt->depth >= 0) &&
Daniel Veillard971771e2005-07-09 17:32:57 +00001583 (vctxt->inode != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001584 node = vctxt->inode->node;
Daniel Veillard971771e2005-07-09 17:32:57 +00001585 }
1586 if ((node == NULL) && (vctxt->parserCtxt != NULL) &&
1587 (vctxt->parserCtxt->input != NULL)) {
1588 file = vctxt->parserCtxt->input->filename;
1589 line = vctxt->parserCtxt->input->line;
1590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001591 __xmlRaiseError(schannel, channel, data, ctxt,
1592 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001593 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001594 (const char *) str1, (const char *) str2,
1595 (const char *) str3, 0, 0, msg, str1, str2, str3);
1596
1597 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1598 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1599
1600 pctxt->nberrors++;
1601 pctxt->err = error;
1602 channel = pctxt->error;
1603 schannel = pctxt->serror;
1604 data = pctxt->userData;
1605 __xmlRaiseError(schannel, channel, data, ctxt,
1606 node, XML_FROM_SCHEMASP,
1607 error, XML_ERR_ERROR, NULL, 0,
1608 (const char *) str1, (const char *) str2,
1609 (const char *) str3, 0, 0, msg, str1, str2, str3);
1610 } else {
1611 TODO
1612 }
1613 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001614}
1615
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001616static void
1617xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1618 int error, xmlNodePtr node, const char *msg,
1619 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001620{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001621 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001622}
1623
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001624static xmlChar *
1625xmlSchemaFormatNodeForError(xmlChar ** msg,
1626 xmlSchemaAbstractCtxtPtr actxt,
1627 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001628{
1629 xmlChar *str = NULL;
1630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001631 if (node != NULL) {
1632 /*
1633 * Work on tree nodes.
1634 */
1635 if (node->type == XML_ATTRIBUTE_NODE) {
1636 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001637
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001638 *msg = xmlStrdup(BAD_CAST "Element '");
1639 if (elem->ns != NULL)
1640 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1641 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001642 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001643 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1644 NULL, elem->name));
1645 FREE_AND_NULL(str);
1646 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1647 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1648 } else {
1649 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001650 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001651 if (node->ns != NULL)
1652 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1653 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001654 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001655 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1656 NULL, node->name));
1657 FREE_AND_NULL(str);
1658 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1659 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1660 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1661 /*
1662 * Work on node infos.
1663 */
1664 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1665 xmlSchemaNodeInfoPtr ielem =
1666 vctxt->elemInfos[vctxt->depth];
1667
1668 *msg = xmlStrdup(BAD_CAST "Element '");
1669 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1670 ielem->nsName, ielem->localName));
1671 FREE_AND_NULL(str);
1672 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1673 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1674 } else {
1675 *msg = xmlStrdup(BAD_CAST "Element '");
1676 }
1677 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1678 vctxt->inode->nsName, vctxt->inode->localName));
1679 FREE_AND_NULL(str);
1680 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1681 } else {
1682 TODO
1683 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001684 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001685 /*
1686 * VAL TODO: The output of the given schema component is currently
1687 * disabled.
1688 */
1689#if 0
1690 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1691 *msg = xmlStrcat(*msg, BAD_CAST " [");
1692 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1693 NULL, type, NULL, 0));
1694 FREE_AND_NULL(str)
1695 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001697#endif
1698 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001699}
1700
Daniel Veillardc0826a72004-08-10 14:17:33 +00001701static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001702xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1703 const char *funcName,
1704 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001705{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001706 xmlChar *msg = NULL;
1707
1708 msg = xmlStrdup(BAD_CAST "Internal error: ");
1709 msg = xmlStrcat(msg, BAD_CAST funcName);
1710 msg = xmlStrcat(msg, BAD_CAST ", ");
1711 msg = xmlStrcat(msg, BAD_CAST message);
1712 msg = xmlStrcat(msg, BAD_CAST ".\n");
1713
1714 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1715 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1716 (const char *) msg, NULL, NULL);
1717
1718 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1719 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1720 (const char *) msg, NULL, NULL);
1721
1722 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001723}
1724
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001725static void
1726xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1727 xmlParserErrors error,
1728 xmlNodePtr node,
1729 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1730 const char *message,
1731 const xmlChar *str1,
1732 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001733{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001734 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001735
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001736 xmlSchemaFormatNodeForError(&msg, actxt, node);
1737 msg = xmlStrcat(msg, (const xmlChar *) message);
1738 msg = xmlStrcat(msg, BAD_CAST ".\n");
1739 xmlSchemaErr(actxt, error, node,
1740 (const char *) msg, str1, str2);
1741 FREE_AND_NULL(msg)
1742}
1743
1744static int
1745xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1746 xmlNodePtr node)
1747{
1748 if (node != NULL)
1749 return (node->type);
1750 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1751 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1752 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1753 return (-1);
1754}
1755
1756static int
1757xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1758{
1759 switch (item->type) {
1760 case XML_SCHEMA_TYPE_COMPLEX:
1761 case XML_SCHEMA_TYPE_SIMPLE:
1762 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1763 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001764 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001765 case XML_SCHEMA_TYPE_GROUP:
1766 return (1);
1767 case XML_SCHEMA_TYPE_ELEMENT:
1768 if ( ((xmlSchemaElementPtr) item)->flags &
1769 XML_SCHEMAS_ELEM_GLOBAL)
1770 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001771 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001772 case XML_SCHEMA_TYPE_ATTRIBUTE:
1773 if ( ((xmlSchemaAttributePtr) item)->flags &
1774 XML_SCHEMAS_ATTR_GLOBAL)
1775 return(1);
1776 break;
1777 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001778 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001779 return(1);
1780 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001781 return (0);
1782}
1783
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001784static void
1785xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1786 xmlParserErrors error,
1787 xmlNodePtr node,
1788 const xmlChar *value,
1789 xmlSchemaTypePtr type,
1790 int displayValue)
1791{
1792 xmlChar *msg = NULL;
1793
1794 xmlSchemaFormatNodeForError(&msg, actxt, node);
1795
1796 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1797 XML_ATTRIBUTE_NODE))
1798 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1799 else
1800 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1801 "value of ");
1802
1803 if (! xmlSchemaIsGlobalItem(type))
1804 msg = xmlStrcat(msg, BAD_CAST "the local ");
1805 else
1806 msg = xmlStrcat(msg, BAD_CAST "the ");
1807
1808 if (VARIETY_ATOMIC(type))
1809 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1810 else if (VARIETY_LIST(type))
1811 msg = xmlStrcat(msg, BAD_CAST "list type");
1812 else if (VARIETY_UNION(type))
1813 msg = xmlStrcat(msg, BAD_CAST "union type");
1814
1815 if (xmlSchemaIsGlobalItem(type)) {
1816 xmlChar *str = NULL;
1817 msg = xmlStrcat(msg, BAD_CAST " '");
1818 if (type->builtInType != 0) {
1819 msg = xmlStrcat(msg, BAD_CAST "xs:");
1820 msg = xmlStrcat(msg, type->name);
1821 } else
1822 msg = xmlStrcat(msg,
1823 xmlSchemaFormatQName(&str,
1824 type->targetNamespace, type->name));
1825 msg = xmlStrcat(msg, BAD_CAST "'");
1826 FREE_AND_NULL(str);
1827 }
1828 msg = xmlStrcat(msg, BAD_CAST ".\n");
1829 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1830 XML_ATTRIBUTE_NODE))
1831 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1832 else
1833 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1834 FREE_AND_NULL(msg)
1835}
1836
Daniel Veillardc0826a72004-08-10 14:17:33 +00001837static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001838xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1839 xmlSchemaNodeInfoPtr ni,
1840 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001841{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001842 if (node != NULL) {
1843 if (node->ns != NULL)
1844 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1845 else
1846 return (xmlSchemaFormatQName(str, NULL, node->name));
1847 } else if (ni != NULL)
1848 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1849 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001850}
1851
Daniel Veillardc0826a72004-08-10 14:17:33 +00001852static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001853xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1854 xmlParserErrors error,
1855 xmlSchemaAttrInfoPtr ni,
1856 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001857{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001858 xmlChar *msg = NULL, *str = NULL;
1859
1860 xmlSchemaFormatNodeForError(&msg, actxt, node);
1861 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1862 xmlSchemaErr(actxt, error, node, (const char *) msg,
1863 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1864 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001865 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001866 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001867}
1868
Daniel Veillardc0826a72004-08-10 14:17:33 +00001869static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001870xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1871 xmlParserErrors error,
1872 xmlNodePtr node,
1873 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001874 const char *message,
1875 int nbval,
1876 int nbneg,
1877 xmlChar **values)
1878{
1879 xmlChar *str = NULL, *msg = NULL;
1880 xmlChar *localName, *nsName;
1881 const xmlChar *cur, *end;
1882 int i;
1883
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001884 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001885 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001886 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001887 /*
1888 * Note that is does not make sense to report that we have a
1889 * wildcard here, since the wildcard might be unfolded into
1890 * multiple transitions.
1891 */
1892 if (nbval + nbneg > 0) {
1893 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001894 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001895 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001896 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001897 nsName = NULL;
1898
1899 for (i = 0; i < nbval + nbneg; i++) {
1900 cur = values[i];
1901 /*
1902 * Get the local name.
1903 */
1904 localName = NULL;
1905
1906 end = cur;
1907 if (*end == '*') {
1908 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001909 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001910 } else {
1911 while ((*end != 0) && (*end != '|'))
1912 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001913 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001914 }
1915 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001916 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001917 /*
1918 * Skip "*|*" if they come with negated expressions, since
1919 * they represent the same negated wildcard.
1920 */
1921 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1922 /*
1923 * Get the namespace name.
1924 */
1925 cur = end;
1926 if (*end == '*') {
1927 nsName = xmlStrdup(BAD_CAST "{*}");
1928 } else {
1929 while (*end != 0)
1930 end++;
1931
1932 if (i >= nbval)
1933 nsName = xmlStrdup(BAD_CAST "{##other:");
1934 else
1935 nsName = xmlStrdup(BAD_CAST "{");
1936
1937 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1938 nsName = xmlStrcat(nsName, BAD_CAST "}");
1939 }
1940 str = xmlStrcat(str, BAD_CAST nsName);
1941 FREE_AND_NULL(nsName)
1942 } else {
1943 FREE_AND_NULL(localName);
1944 continue;
1945 }
1946 }
1947 str = xmlStrcat(str, BAD_CAST localName);
1948 FREE_AND_NULL(localName);
1949
1950 if (i < nbval + nbneg -1)
1951 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001952 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001953 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001954 msg = xmlStrcat(msg, BAD_CAST str);
1955 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001956 } else
1957 msg = xmlStrcat(msg, BAD_CAST "\n");
1958 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001959 xmlFree(msg);
1960}
1961
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001962static void
1963xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1964 xmlParserErrors error,
1965 xmlNodePtr node,
1966 const xmlChar *value,
1967 unsigned long length,
1968 xmlSchemaTypePtr type,
1969 xmlSchemaFacetPtr facet,
1970 const char *message,
1971 const xmlChar *str1,
1972 const xmlChar *str2)
1973{
1974 xmlChar *str = NULL, *msg = NULL;
1975 xmlSchemaTypeType facetType;
1976 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1977
1978 xmlSchemaFormatNodeForError(&msg, actxt, node);
1979 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1980 facetType = XML_SCHEMA_FACET_ENUMERATION;
1981 /*
1982 * If enumerations are validated, one must not expect the
1983 * facet to be given.
1984 */
1985 } else
1986 facetType = facet->type;
1987 msg = xmlStrcat(msg, BAD_CAST "[");
1988 msg = xmlStrcat(msg, BAD_CAST "facet '");
1989 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
1990 msg = xmlStrcat(msg, BAD_CAST "'] ");
1991 if (message == NULL) {
1992 /*
1993 * Use a default message.
1994 */
1995 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1996 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1997 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1998
1999 char len[25], actLen[25];
2000
2001 /* FIXME, TODO: What is the max expected string length of the
2002 * this value?
2003 */
2004 if (nodeType == XML_ATTRIBUTE_NODE)
2005 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2006 else
2007 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2008
2009 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2010 snprintf(actLen, 24, "%lu", length);
2011
2012 if (facetType == XML_SCHEMA_FACET_LENGTH)
2013 msg = xmlStrcat(msg,
2014 BAD_CAST "this differs from the allowed length of '%s'.\n");
2015 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2016 msg = xmlStrcat(msg,
2017 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2018 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2019 msg = xmlStrcat(msg,
2020 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2021
2022 if (nodeType == XML_ATTRIBUTE_NODE)
2023 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2024 value, (const xmlChar *) actLen, (const xmlChar *) len);
2025 else
2026 xmlSchemaErr(actxt, error, node, (const char *) msg,
2027 (const xmlChar *) actLen, (const xmlChar *) len);
2028
2029 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2030 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2031 "of the set {%s}.\n");
2032 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2033 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2034 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2035 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2036 "by the pattern '%s'.\n");
2037 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2038 facet->value);
2039 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2040 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2041 "minimum value allowed ('%s').\n");
2042 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2043 facet->value);
2044 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2045 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2046 "maximum value allowed ('%s').\n");
2047 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2048 facet->value);
2049 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2050 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2051 "'%s'.\n");
2052 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2053 facet->value);
2054 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2055 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2056 "'%s'.\n");
2057 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2058 facet->value);
2059 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2060 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2061 "digits than are allowed ('%s').\n");
2062 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2063 facet->value);
2064 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2065 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2066 "digits than are allowed ('%s').\n");
2067 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2068 facet->value);
2069 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2070 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2071 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2072 } else {
2073 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2074 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2075 }
2076 } else {
2077 msg = xmlStrcat(msg, (const xmlChar *) message);
2078 msg = xmlStrcat(msg, BAD_CAST ".\n");
2079 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2080 }
2081 FREE_AND_NULL(str)
2082 xmlFree(msg);
2083}
2084
2085#define VERROR(err, type, msg) \
2086 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2087
2088#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2089
2090#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2091
2092#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2093
2094
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002095/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002096 * xmlSchemaPMissingAttrErr:
2097 * @ctxt: the schema validation context
2098 * @ownerDes: the designation of the owner
2099 * @ownerName: the name of the owner
2100 * @ownerItem: the owner as a schema object
2101 * @ownerElem: the owner as an element node
2102 * @node: the parent element node of the missing attribute node
2103 * @type: the corresponding type of the attribute node
2104 *
2105 * Reports an illegal attribute.
2106 */
2107static void
2108xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002109 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002110 xmlSchemaTypePtr ownerItem,
2111 xmlNodePtr ownerElem,
2112 const char *name,
2113 const char *message)
2114{
2115 xmlChar *des = NULL;
2116
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002117 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2118
Daniel Veillardc0826a72004-08-10 14:17:33 +00002119 if (message != NULL)
2120 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002121 else
2122 xmlSchemaPErr(ctxt, ownerElem, error,
2123 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002124 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002125 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002126}
2127
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002128
Daniel Veillardc0826a72004-08-10 14:17:33 +00002129/**
2130 * xmlSchemaPResCompAttrErr:
2131 * @ctxt: the schema validation context
2132 * @error: the error code
2133 * @ownerDes: the designation of the owner
2134 * @ownerItem: the owner as a schema object
2135 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002136 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002137 * @refName: the referenced local name
2138 * @refURI: the referenced namespace URI
2139 * @message: optional message
2140 *
2141 * Used to report QName attribute values that failed to resolve
2142 * to schema components.
2143 */
2144static void
2145xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002146 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002147 xmlSchemaTypePtr ownerItem,
2148 xmlNodePtr ownerElem,
2149 const char *name,
2150 const xmlChar *refName,
2151 const xmlChar *refURI,
2152 xmlSchemaTypeType refType,
2153 const char *refTypeStr)
2154{
2155 xmlChar *des = NULL, *strA = NULL;
2156
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002157 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002158 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002159 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2160 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002161 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2163 "%s.\n", BAD_CAST des, BAD_CAST name,
2164 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002165 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002166 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002167 FREE_AND_NULL(strA)
2168}
2169
William M. Brack2f2a6632004-08-20 23:09:47 +00002170/**
2171 * xmlSchemaPCustomAttrErr:
2172 * @ctxt: the schema parser context
2173 * @error: the error code
2174 * @ownerDes: the designation of the owner
2175 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002176 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002177 *
2178 * Reports an illegal attribute during the parse.
2179 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002180static void
2181xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002182 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002183 xmlChar **ownerDes,
2184 xmlSchemaTypePtr ownerItem,
2185 xmlAttrPtr attr,
2186 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002187{
2188 xmlChar *des = NULL;
2189
2190 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002191 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002192 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002193 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002194 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002195 } else
2196 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002198 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002199 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2200 if (ownerDes == NULL)
2201 FREE_AND_NULL(des);
2202}
2203
2204/**
2205 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002206 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002207 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002208 * @ownerDes: the designation of the attribute's owner
2209 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002210 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002211 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002212 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002213 */
2214static void
2215xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002216 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002217 xmlChar **ownerDes,
2218 xmlSchemaTypePtr ownerItem,
2219 xmlAttrPtr attr)
2220{
2221 xmlChar *des = NULL, *strA = NULL;
2222
2223 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002224 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002225 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002226 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002227 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002228 } else
2229 des = *ownerDes;
2230 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2231 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2232 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002233 if (ownerDes == NULL)
2234 FREE_AND_NULL(des);
2235 FREE_AND_NULL(strA);
2236}
2237
William M. Brack2f2a6632004-08-20 23:09:47 +00002238/**
2239 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002240 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002241 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002242 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002243 * @itemElem: the node of the schema item
2244 *
2245 * Creates a designation for an item.
2246 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002247static void
2248xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002249 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002250 xmlSchemaTypePtr item,
2251 xmlNodePtr itemElem)
2252{
2253 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002254 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002255 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002256 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002257 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002258 } else
2259 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002260}
2261
William M. Brack2f2a6632004-08-20 23:09:47 +00002262/**
2263 * xmlSchemaPCustomErr:
2264 * @ctxt: the schema parser context
2265 * @error: the error code
2266 * @itemDes: the designation of the schema item
2267 * @item: the schema item
2268 * @itemElem: the node of the schema item
2269 * @message: the error message
2270 * @str1: an optional param for the error message
2271 * @str2: an optional param for the error message
2272 * @str3: an optional param for the error message
2273 *
2274 * Reports an error during parsing.
2275 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002276static void
2277xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002278 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002279 xmlChar **itemDes,
2280 xmlSchemaTypePtr item,
2281 xmlNodePtr itemElem,
2282 const char *message,
2283 const xmlChar *str1,
2284 const xmlChar *str2,
2285 const xmlChar *str3)
2286{
2287 xmlChar *des = NULL, *msg = NULL;
2288
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002289 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002290 msg = xmlStrdup(BAD_CAST "%s: ");
2291 msg = xmlStrcat(msg, (const xmlChar *) message);
2292 msg = xmlStrcat(msg, BAD_CAST ".\n");
2293 if ((itemElem == NULL) && (item != NULL))
2294 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002295 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002296 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2297 if (itemDes == NULL)
2298 FREE_AND_NULL(des);
2299 FREE_AND_NULL(msg);
2300}
2301
William M. Brack2f2a6632004-08-20 23:09:47 +00002302/**
2303 * xmlSchemaPCustomErr:
2304 * @ctxt: the schema parser context
2305 * @error: the error code
2306 * @itemDes: the designation of the schema item
2307 * @item: the schema item
2308 * @itemElem: the node of the schema item
2309 * @message: the error message
2310 * @str1: the optional param for the error message
2311 *
2312 * Reports an error during parsing.
2313 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002314static void
2315xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002316 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002317 xmlChar **itemDes,
2318 xmlSchemaTypePtr item,
2319 xmlNodePtr itemElem,
2320 const char *message,
2321 const xmlChar *str1)
2322{
2323 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2324 str1, NULL, NULL);
2325}
2326
William M. Brack2f2a6632004-08-20 23:09:47 +00002327/**
2328 * xmlSchemaPAttrUseErr:
2329 * @ctxt: the schema parser context
2330 * @error: the error code
2331 * @itemDes: the designation of the schema type
2332 * @item: the schema type
2333 * @itemElem: the node of the schema type
2334 * @attr: the invalid schema attribute
2335 * @message: the error message
2336 * @str1: the optional param for the error message
2337 *
2338 * Reports an attribute use error during parsing.
2339 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002340static void
2341xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002342 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002343 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002344 const xmlSchemaAttributePtr attr,
2345 const char *message,
2346 const xmlChar *str1)
2347{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002348 xmlChar *str = NULL, *msg = NULL;
2349 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2350 msg = xmlStrcat(msg, BAD_CAST ", ");
2351 msg = xmlStrcat(msg,
2352 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2353 (xmlSchemaTypePtr) attr, NULL));
2354 FREE_AND_NULL(str);
2355 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002356 msg = xmlStrcat(msg, (const xmlChar *) message);
2357 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002358 xmlSchemaPErr(ctxt, attr->node, error,
2359 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002360 xmlFree(msg);
2361}
2362
William M. Brack2f2a6632004-08-20 23:09:47 +00002363/**
2364 * xmlSchemaPIllegalFacetAtomicErr:
2365 * @ctxt: the schema parser context
2366 * @error: the error code
2367 * @itemDes: the designation of the type
2368 * @item: the schema type
2369 * @baseItem: the base type of type
2370 * @facet: the illegal facet
2371 *
2372 * Reports an illegal facet for atomic simple types.
2373 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002374static void
2375xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002376 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002377 xmlChar **itemDes,
2378 xmlSchemaTypePtr item,
2379 xmlSchemaTypePtr baseItem,
2380 xmlSchemaFacetPtr facet)
2381{
2382 xmlChar *des = NULL, *strT = NULL;
2383
2384 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2385 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2386 "%s: The facet '%s' is not allowed on types derived from the "
2387 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002388 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002389 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002390 NULL, NULL);
2391 if (itemDes == NULL)
2392 FREE_AND_NULL(des);
2393 FREE_AND_NULL(strT);
2394}
2395
William M. Brack2f2a6632004-08-20 23:09:47 +00002396/**
2397 * xmlSchemaPIllegalFacetListUnionErr:
2398 * @ctxt: the schema parser context
2399 * @error: the error code
2400 * @itemDes: the designation of the schema item involved
2401 * @item: the schema item involved
2402 * @facet: the illegal facet
2403 *
2404 * Reports an illegal facet for <list> and <union>.
2405 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002406static void
2407xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002408 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002409 xmlChar **itemDes,
2410 xmlSchemaTypePtr item,
2411 xmlSchemaFacetPtr facet)
2412{
2413 xmlChar *des = NULL, *strT = NULL;
2414
2415 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002416 xmlSchemaPErr(ctxt, item->node, error,
2417 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002418 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002419 if (itemDes == NULL)
2420 FREE_AND_NULL(des);
2421 FREE_AND_NULL(strT);
2422}
2423
2424/**
2425 * xmlSchemaPMutualExclAttrErr:
2426 * @ctxt: the schema validation context
2427 * @error: the error code
2428 * @elemDes: the designation of the parent element node
2429 * @attr: the bad attribute node
2430 * @type: the corresponding type of the attribute node
2431 *
2432 * Reports an illegal attribute.
2433 */
2434static void
2435xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2436 xmlParserErrors error,
2437 xmlChar **ownerDes,
2438 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002439 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002440 const char *name1,
2441 const char *name2)
2442{
2443 xmlChar *des = NULL;
2444
2445 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002446 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002447 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002448 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002449 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002450 } else
2451 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002452 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002453 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002454 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2455 if (ownerDes == NULL)
2456 FREE_AND_NULL(des)
2457}
2458
2459/**
2460 * xmlSchemaPSimpleTypeErr:
2461 * @ctxt: the schema validation context
2462 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002463 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002464 * @ownerDes: the designation of the owner
2465 * @ownerItem: the schema object if existent
2466 * @node: the validated node
2467 * @value: the validated value
2468 *
2469 * Reports a simple type validation error.
2470 * TODO: Should this report the value of an element as well?
2471 */
2472static void
2473xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2474 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002475 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002476 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002477 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002478 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002479 const xmlChar *value,
2480 const char *message,
2481 const xmlChar *str1,
2482 const xmlChar *str2)
2483{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002484 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002485
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002486 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487 if (message == NULL) {
2488 /*
2489 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002490 */
2491 if (type != NULL) {
2492 if (node->type == XML_ATTRIBUTE_NODE)
2493 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2494 else
2495 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2496 "valid value of ");
2497 if (! xmlSchemaIsGlobalItem(type))
2498 msg = xmlStrcat(msg, BAD_CAST "the local ");
2499 else
2500 msg = xmlStrcat(msg, BAD_CAST "the ");
2501
2502 if (VARIETY_ATOMIC(type))
2503 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2504 else if (VARIETY_LIST(type))
2505 msg = xmlStrcat(msg, BAD_CAST "list type");
2506 else if (VARIETY_UNION(type))
2507 msg = xmlStrcat(msg, BAD_CAST "union type");
2508
2509 if (xmlSchemaIsGlobalItem(type)) {
2510 xmlChar *str = NULL;
2511 msg = xmlStrcat(msg, BAD_CAST " '");
2512 if (type->builtInType != 0) {
2513 msg = xmlStrcat(msg, BAD_CAST "xs:");
2514 msg = xmlStrcat(msg, type->name);
2515 } else
2516 msg = xmlStrcat(msg,
2517 xmlSchemaFormatQName(&str,
2518 type->targetNamespace, type->name));
2519 msg = xmlStrcat(msg, BAD_CAST "'.");
2520 FREE_AND_NULL(str);
2521 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002522 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002523 if (node->type == XML_ATTRIBUTE_NODE)
2524 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2525 else
2526 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2527 "valid.");
2528 }
2529 if (expected) {
2530 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2531 msg = xmlStrcat(msg, BAD_CAST expected);
2532 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2533 } else
2534 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002535 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002536 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2537 else
2538 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2539 } else {
2540 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2541 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002542 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002543 /* Cleanup. */
2544 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002545}
2546
William M. Brack2f2a6632004-08-20 23:09:47 +00002547/**
2548 * xmlSchemaPContentErr:
2549 * @ctxt: the schema parser context
2550 * @error: the error code
2551 * @onwerDes: the designation of the holder of the content
2552 * @ownerItem: the owner item of the holder of the content
2553 * @ownerElem: the node of the holder of the content
2554 * @child: the invalid child node
2555 * @message: the optional error message
2556 * @content: the optional string describing the correct content
2557 *
2558 * Reports an error concerning the content of a schema element.
2559 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002560static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002561xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002562 xmlParserErrors error,
2563 xmlChar **ownerDes,
2564 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002565 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002566 xmlNodePtr child,
2567 const char *message,
2568 const char *content)
2569{
2570 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002571
Daniel Veillardc0826a72004-08-10 14:17:33 +00002572 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002573 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002574 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002575 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002576 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002577 } else
2578 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002579 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002580 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2581 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002582 BAD_CAST des, BAD_CAST message);
2583 else {
2584 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002585 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2586 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002587 BAD_CAST des, BAD_CAST content);
2588 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002589 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2590 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002591 BAD_CAST des, NULL);
2592 }
2593 }
2594 if (ownerDes == NULL)
2595 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002596}
2597
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002598/************************************************************************
2599 * *
2600 * Streamable error functions *
2601 * *
2602 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002603
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002604
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002605
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002606
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002607/************************************************************************
2608 * *
2609 * Validation helper functions *
2610 * *
2611 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002612
Daniel Veillardc0826a72004-08-10 14:17:33 +00002613
Daniel Veillard4255d502002-04-16 15:50:10 +00002614/************************************************************************
2615 * *
2616 * Allocation functions *
2617 * *
2618 ************************************************************************/
2619
2620/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002621 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002622 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002623 *
2624 * Allocate a new Schema structure.
2625 *
2626 * Returns the newly allocated structure or NULL in case or error
2627 */
2628static xmlSchemaPtr
2629xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2630{
2631 xmlSchemaPtr ret;
2632
2633 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2634 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002635 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002636 return (NULL);
2637 }
2638 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002639 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002640 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002641
2642 return (ret);
2643}
2644
2645/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002646 * xmlSchemaNewSchema:
2647 * @ctxt: a schema validation context
2648 *
2649 * Allocate a new Schema structure.
2650 *
2651 * Returns the newly allocated structure or NULL in case or error
2652 */
2653static xmlSchemaAssemblePtr
2654xmlSchemaNewAssemble(void)
2655{
2656 xmlSchemaAssemblePtr ret;
2657
2658 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2659 if (ret == NULL) {
2660 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2661 return (NULL);
2662 }
2663 memset(ret, 0, sizeof(xmlSchemaAssemble));
2664 ret->items = NULL;
2665 return (ret);
2666}
2667
2668/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002669 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002670 *
2671 * Allocate a new Facet structure.
2672 *
2673 * Returns the newly allocated structure or NULL in case or error
2674 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002675xmlSchemaFacetPtr
2676xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002677{
2678 xmlSchemaFacetPtr ret;
2679
2680 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2681 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002682 return (NULL);
2683 }
2684 memset(ret, 0, sizeof(xmlSchemaFacet));
2685
2686 return (ret);
2687}
2688
2689/**
2690 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002691 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002692 * @node: a node
2693 *
2694 * Allocate a new annotation structure.
2695 *
2696 * Returns the newly allocated structure or NULL in case or error
2697 */
2698static xmlSchemaAnnotPtr
2699xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2700{
2701 xmlSchemaAnnotPtr ret;
2702
2703 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2704 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002705 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002706 return (NULL);
2707 }
2708 memset(ret, 0, sizeof(xmlSchemaAnnot));
2709 ret->content = node;
2710 return (ret);
2711}
2712
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002713static xmlSchemaItemListPtr
2714xmlSchemaNewItemList(void)
2715{
2716 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002717
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002718 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2719 if (ret == NULL) {
2720 xmlSchemaPErrMemory(NULL,
2721 "allocating an item list structure", NULL);
2722 return (NULL);
2723 }
2724 memset(ret, 0, sizeof(xmlSchemaItemList));
2725 return (ret);
2726}
2727
2728/**
2729 * xmlSchemaAddElementSubstitutionMember:
2730 * @pctxt: a schema parser context
2731 * @head: the head of the substitution group
2732 * @member: the new member of the substitution group
2733 *
2734 * Allocate a new annotation structure.
2735 *
2736 * Returns the newly allocated structure or NULL in case or error
2737 */
2738static int
2739xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2740 xmlSchemaElementPtr head,
2741 xmlSchemaElementPtr member)
2742{
2743 xmlSchemaSubstGroupPtr substGroup;
2744
2745 if (pctxt == NULL)
2746 return (-1);
2747
2748 if (pctxt->substGroups == NULL) {
2749 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2750 if (pctxt->substGroups == NULL)
2751 return (-1);
2752 }
2753 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2754 head->targetNamespace);
2755 if (substGroup == NULL) {
2756 int res;
2757
2758 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2759 if (substGroup == NULL) {
2760 xmlSchemaPErrMemory(NULL,
2761 "xmlSchemaAddElementSubstitution, allocating a substitution "
2762 "group container",
2763 NULL);
2764 return (-1);
2765 }
2766 substGroup->members = xmlSchemaNewItemList();
2767 if (substGroup->members == NULL) {
2768 xmlFree(substGroup);
2769 return (-1);
2770 }
2771 substGroup->head = head;
2772
2773 res = xmlHashAddEntry2(pctxt->substGroups,
2774 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002775 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002776 xmlFree(substGroup->members);
2777 xmlFree(substGroup);
2778 xmlSchemaPErr(pctxt, member->node,
2779 XML_SCHEMAP_INTERNAL,
2780 "Internal error: xmlSchemaAddElementSubstitution, "
2781 "failed to add a new substitution group container for "
2782 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002783 return (-1);
2784 }
2785 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002786 if (substGroup->members->items == NULL) {
2787 substGroup->members->items = (void **) xmlMalloc(
2788 5 * sizeof(xmlSchemaElementPtr));
2789 if (substGroup->members->items == NULL) {
2790 xmlSchemaPErrMemory(NULL,
2791 "allocating list of substitution group members", NULL);
2792 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002793 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002794 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002795 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002796 substGroup->members->nbItems) {
2797 substGroup->members->sizeItems *= 2;
2798 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002799 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002800 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2801 if (substGroup->members->items == NULL) {
2802 xmlSchemaPErrMemory(NULL,
2803 "re-allocating list of substitution group members", NULL);
2804 substGroup->members->sizeItems = 0;
2805 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002806 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002807 }
2808 ((xmlSchemaElementPtr *) substGroup->members->items)
2809 [substGroup->members->nbItems++] = (void *) member;
2810 return (0);
2811}
2812
2813/**
2814 * xmlSchemaGetElementSubstitutionGroup:
2815 * @pctxt: a schema parser context
2816 * @head: the head of the substitution group
2817 * @member: the new member of the substitution group
2818 *
2819 * Allocate a new annotation structure.
2820 *
2821 * Returns the newly allocated structure or NULL in case or error
2822 */
2823static xmlSchemaSubstGroupPtr
2824xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2825 xmlSchemaElementPtr head)
2826{
2827 if (pctxt == NULL)
2828 return (NULL);
2829
2830 if (pctxt->substGroups == NULL)
2831 return (NULL);
2832
2833 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2834 head->name, head->targetNamespace));
2835}
2836
2837/**
2838 * xmlSchemaFreeItemList:
2839 * @annot: a schema type structure
2840 *
2841 * Deallocate a annotation structure
2842 */
2843static void
2844xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2845{
2846 if (list == NULL)
2847 return;
2848 if (list->items != NULL)
2849 xmlFree(list->items);
2850 xmlFree(list);
2851}
2852
Daniel Veillard4255d502002-04-16 15:50:10 +00002853/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002854 * xmlSchemaFreeAnnot:
2855 * @annot: a schema type structure
2856 *
2857 * Deallocate a annotation structure
2858 */
2859static void
2860xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2861{
2862 if (annot == NULL)
2863 return;
2864 xmlFree(annot);
2865}
2866
2867/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002868 * xmlSchemaFreeImport:
2869 * @import: a schema import structure
2870 *
2871 * Deallocate an import structure
2872 */
2873static void
2874xmlSchemaFreeImport(xmlSchemaImportPtr import)
2875{
2876 if (import == NULL)
2877 return;
2878
2879 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002880 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002881 xmlFree(import);
2882}
2883
2884/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002885 * xmlSchemaFreeInclude:
2886 * @include: a schema include structure
2887 *
2888 * Deallocate an include structure
2889 */
2890static void
2891xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2892{
2893 if (include == NULL)
2894 return;
2895
2896 xmlFreeDoc(include->doc);
2897 xmlFree(include);
2898}
2899
2900/**
2901 * xmlSchemaFreeIncludeList:
2902 * @includes: a schema include list
2903 *
2904 * Deallocate an include structure
2905 */
2906static void
2907xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2908{
2909 xmlSchemaIncludePtr next;
2910
2911 while (includes != NULL) {
2912 next = includes->next;
2913 xmlSchemaFreeInclude(includes);
2914 includes = next;
2915 }
2916}
2917
2918/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002919 * xmlSchemaFreeNotation:
2920 * @schema: a schema notation structure
2921 *
2922 * Deallocate a Schema Notation structure.
2923 */
2924static void
2925xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2926{
2927 if (nota == NULL)
2928 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002929 xmlFree(nota);
2930}
2931
2932/**
2933 * xmlSchemaFreeAttribute:
2934 * @schema: a schema attribute structure
2935 *
2936 * Deallocate a Schema Attribute structure.
2937 */
2938static void
2939xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2940{
2941 if (attr == NULL)
2942 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002943 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002944 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002945 if (attr->defVal != NULL)
2946 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002947 xmlFree(attr);
2948}
2949
2950/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002951 * xmlSchemaFreeWildcardNsSet:
2952 * set: a schema wildcard namespace
2953 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002954 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002955 */
2956static void
2957xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2958{
2959 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002960
Daniel Veillard3646d642004-06-02 19:19:14 +00002961 while (set != NULL) {
2962 next = set->next;
2963 xmlFree(set);
2964 set = next;
2965 }
2966}
2967
2968/**
2969 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002970 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002971 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002972 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002973 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002974void
Daniel Veillard3646d642004-06-02 19:19:14 +00002975xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2976{
2977 if (wildcard == NULL)
2978 return;
2979 if (wildcard->annot != NULL)
2980 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002981 if (wildcard->nsSet != NULL)
2982 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2983 if (wildcard->negNsSet != NULL)
2984 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002985 xmlFree(wildcard);
2986}
2987
2988/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002989 * xmlSchemaFreeAttributeGroup:
2990 * @schema: a schema attribute group structure
2991 *
2992 * Deallocate a Schema Attribute Group structure.
2993 */
2994static void
2995xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2996{
2997 if (attr == NULL)
2998 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002999 if (attr->annot != NULL)
3000 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003001 xmlFree(attr);
3002}
3003
3004/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003005 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003006 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003007 *
3008 * Deallocate a list of schema attribute uses.
3009 */
3010static void
3011xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3012{
3013 xmlSchemaAttributeLinkPtr next;
3014
3015 while (attrUse != NULL) {
3016 next = attrUse->next;
3017 xmlFree(attrUse);
3018 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003019 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003020}
3021
3022/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003023 * xmlSchemaFreeQNameRef:
3024 * @item: a QName reference structure
3025 *
3026 * Deallocatea a QName reference structure.
3027 */
3028static void
3029xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3030{
3031 xmlFree(item);
3032}
3033
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003034/**
3035 * xmlSchemaFreeQNameRef:
3036 * @item: a QName reference structure
3037 *
3038 * Deallocatea a QName reference structure.
3039 */
3040static void
3041xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3042{
3043 if (item == NULL)
3044 return;
3045 if (item->members != NULL)
3046 xmlSchemaFreeItemList(item->members);
3047 xmlFree(item);
3048}
3049
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003050static int
3051xmlSchemaAddVolatile(xmlSchemaPtr schema,
3052 xmlSchemaBasicItemPtr item)
3053{
3054 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003055
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003056 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003057 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003058 if (schema->volatiles == NULL) {
3059 xmlSchemaPErrMemory(NULL,
3060 "allocating list of volatiles", NULL);
3061 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003062 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003063 }
3064 list = (xmlSchemaItemListPtr) schema->volatiles;
3065 if (list->items == NULL) {
3066 list->items = (void **) xmlMalloc(
3067 20 * sizeof(xmlSchemaBasicItemPtr));
3068 if (list->items == NULL) {
3069 xmlSchemaPErrMemory(NULL,
3070 "allocating new volatile item buffer", NULL);
3071 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003072 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003073 list->sizeItems = 20;
3074 } else if (list->sizeItems <= list->nbItems) {
3075 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003076 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003077 list->sizeItems * sizeof(xmlSchemaTypePtr));
3078 if (list->items == NULL) {
3079 xmlSchemaPErrMemory(NULL,
3080 "growing volatile item buffer", NULL);
3081 list->sizeItems = 0;
3082 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003083 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003084 }
3085 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3086 return (0);
3087}
3088
3089/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003090 * xmlSchemaFreeTypeLinkList:
3091 * @alink: a type link
3092 *
3093 * Deallocate a list of types.
3094 */
3095static void
3096xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3097{
3098 xmlSchemaTypeLinkPtr next;
3099
3100 while (link != NULL) {
3101 next = link->next;
3102 xmlFree(link);
3103 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003104 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003105}
3106
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003107static void
3108xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3109{
3110 xmlSchemaIDCStateObjPtr next;
3111 while (sto != NULL) {
3112 next = sto->next;
3113 if (sto->history != NULL)
3114 xmlFree(sto->history);
3115 if (sto->xpathCtxt != NULL)
3116 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3117 xmlFree(sto);
3118 sto = next;
3119 }
3120}
3121
3122/**
3123 * xmlSchemaFreeIDC:
3124 * @idc: a identity-constraint definition
3125 *
3126 * Deallocates an identity-constraint definition.
3127 */
3128static void
3129xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3130{
3131 xmlSchemaIDCSelectPtr cur, prev;
3132
3133 if (idcDef == NULL)
3134 return;
3135 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003136 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003137 /* Selector */
3138 if (idcDef->selector != NULL) {
3139 if (idcDef->selector->xpathComp != NULL)
3140 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3141 xmlFree(idcDef->selector);
3142 }
3143 /* Fields */
3144 if (idcDef->fields != NULL) {
3145 cur = idcDef->fields;
3146 do {
3147 prev = cur;
3148 cur = cur->next;
3149 if (prev->xpathComp != NULL)
3150 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003151 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003152 } while (cur != NULL);
3153 }
3154 xmlFree(idcDef);
3155}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003156
Daniel Veillard01fa6152004-06-29 17:04:39 +00003157/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 * xmlSchemaFreeElement:
3159 * @schema: a schema element structure
3160 *
3161 * Deallocate a Schema Element structure.
3162 */
3163static void
3164xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3165{
3166 if (elem == NULL)
3167 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003168 if (elem->annot != NULL)
3169 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003170 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003171 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003172 if (elem->defVal != NULL)
3173 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003174 xmlFree(elem);
3175}
3176
3177/**
3178 * xmlSchemaFreeFacet:
3179 * @facet: a schema facet structure
3180 *
3181 * Deallocate a Schema Facet structure.
3182 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003183void
Daniel Veillard4255d502002-04-16 15:50:10 +00003184xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3185{
3186 if (facet == NULL)
3187 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003188 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003189 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003190 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003191 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003192 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003193 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003194 xmlFree(facet);
3195}
3196
3197/**
3198 * xmlSchemaFreeType:
3199 * @type: a schema type structure
3200 *
3201 * Deallocate a Schema Type structure.
3202 */
3203void
3204xmlSchemaFreeType(xmlSchemaTypePtr type)
3205{
3206 if (type == NULL)
3207 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003208 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003209 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003212
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003213 facet = type->facets;
3214 while (facet != NULL) {
3215 next = facet->next;
3216 xmlSchemaFreeFacet(facet);
3217 facet = next;
3218 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003219 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003220 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3221 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003222 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003223 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003224 if (type->memberTypes != NULL)
3225 xmlSchemaFreeTypeLinkList(type->memberTypes);
3226 if (type->facetSet != NULL) {
3227 xmlSchemaFacetLinkPtr next, link;
3228
3229 link = type->facetSet;
3230 do {
3231 next = link->next;
3232 xmlFree(link);
3233 link = next;
3234 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003235 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003236 if (type->contModel != NULL)
3237 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003238 xmlFree(type);
3239}
3240
3241/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003242 * xmlSchemaFreeModelGroupDef:
3243 * @item: a schema model group definition
3244 *
3245 * Deallocates a schema model group definition.
3246 */
3247static void
3248xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3249{
3250 if (item->annot != NULL)
3251 xmlSchemaFreeAnnot(item->annot);
3252 xmlFree(item);
3253}
3254
3255/**
3256 * xmlSchemaFreeModelGroup:
3257 * @item: a schema model group
3258 *
3259 * Deallocates a schema model group structure.
3260 */
3261static void
3262xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3263{
3264 if (item->annot != NULL)
3265 xmlSchemaFreeAnnot(item->annot);
3266 xmlFree(item);
3267}
3268
3269/**
3270 * xmlSchemaFreeParticle:
3271 * @type: a schema type structure
3272 *
3273 * Deallocate a Schema Type structure.
3274 */
3275static void
3276xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3277{
3278 if (item->annot != NULL)
3279 xmlSchemaFreeAnnot(item->annot);
3280 xmlFree(item);
3281}
3282
3283/**
3284 * xmlSchemaFreeMiscComponents:
3285 * @item: a schema component
3286 *
3287 * Deallocates misc. schema component structures.
3288 */
3289static void
3290xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3291{
3292 if (item == NULL)
3293 return;
3294 switch (item->type) {
3295 case XML_SCHEMA_TYPE_PARTICLE:
3296 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3297 return;
3298 case XML_SCHEMA_TYPE_SEQUENCE:
3299 case XML_SCHEMA_TYPE_CHOICE:
3300 case XML_SCHEMA_TYPE_ALL:
3301 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3302 return;
3303 case XML_SCHEMA_TYPE_ANY:
3304 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3305 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3306 break;
3307 default:
3308 /* TODO: This should never be hit. */
3309 TODO
3310 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003311 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003312}
3313
3314static void
3315xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3316{
3317 if (schema->volatiles == NULL)
3318 return;
3319 {
3320 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3321 xmlSchemaTreeItemPtr item;
3322 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003323
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003324 for (i = 0; i < list->nbItems; i++) {
3325 if (list->items[i] != NULL) {
3326 item = (xmlSchemaTreeItemPtr) list->items[i];
3327 switch (item->type) {
3328 case XML_SCHEMA_EXTRA_QNAMEREF:
3329 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3330 break;
3331 default:
3332 xmlSchemaFreeMiscComponents(item);
3333 }
3334 }
3335 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003336 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003337 }
3338}
3339/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003340 * xmlSchemaFreeTypeList:
3341 * @type: a schema type structure
3342 *
3343 * Deallocate a Schema Type structure.
3344 */
3345static void
3346xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3347{
3348 xmlSchemaTypePtr next;
3349
3350 while (type != NULL) {
3351 next = type->redef;
3352 xmlSchemaFreeType(type);
3353 type = next;
3354 }
3355}
3356
3357/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003358 * xmlSchemaFree:
3359 * @schema: a schema structure
3360 *
3361 * Deallocate a Schema structure.
3362 */
3363void
3364xmlSchemaFree(xmlSchemaPtr schema)
3365{
3366 if (schema == NULL)
3367 return;
3368
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003369 if (schema->volatiles != NULL)
3370 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003371 if (schema->notaDecl != NULL)
3372 xmlHashFree(schema->notaDecl,
3373 (xmlHashDeallocator) xmlSchemaFreeNotation);
3374 if (schema->attrDecl != NULL)
3375 xmlHashFree(schema->attrDecl,
3376 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3377 if (schema->attrgrpDecl != NULL)
3378 xmlHashFree(schema->attrgrpDecl,
3379 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3380 if (schema->elemDecl != NULL)
3381 xmlHashFree(schema->elemDecl,
3382 (xmlHashDeallocator) xmlSchemaFreeElement);
3383 if (schema->typeDecl != NULL)
3384 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003385 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003386 if (schema->groupDecl != NULL)
3387 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003388 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003389 if (schema->idcDef != NULL)
3390 xmlHashFree(schema->idcDef,
3391 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003392 if (schema->schemasImports != NULL)
3393 xmlHashFree(schema->schemasImports,
3394 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003395 if (schema->includes != NULL) {
3396 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3397 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003398 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003399 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003400 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003401 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003402 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003403 xmlFree(schema);
3404}
3405
3406/************************************************************************
3407 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003408 * Debug functions *
3409 * *
3410 ************************************************************************/
3411
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003412#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003413
Daniel Veillard4255d502002-04-16 15:50:10 +00003414/**
3415 * xmlSchemaElementDump:
3416 * @elem: an element
3417 * @output: the file output
3418 *
3419 * Dump the element
3420 */
3421static void
3422xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003424 const xmlChar * namespace ATTRIBUTE_UNUSED,
3425 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003426{
3427 if (elem == NULL)
3428 return;
3429
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003430 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3431 fprintf(output, "Particle: %s", name);
3432 fprintf(output, ", term element: %s", elem->ref);
3433 if (elem->refNs != NULL)
3434 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003435 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003436 fprintf(output, "Element");
3437 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3438 fprintf(output, " (global)");
3439 fprintf(output, ": %s ", elem->name);
3440 if (namespace != NULL)
3441 fprintf(output, "ns %s", namespace);
3442 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003443 fprintf(output, "\n");
3444 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003445 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003446 if (elem->maxOccurs >= UNBOUNDED)
3447 fprintf(output, "max: unbounded\n");
3448 else if (elem->maxOccurs != 1)
3449 fprintf(output, "max: %d\n", elem->maxOccurs);
3450 else
3451 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003452 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003453 /*
3454 * Misc other properties.
3455 */
3456 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3457 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3458 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3459 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3460 (elem->id != NULL)) {
3461 fprintf(output, " props: ");
3462 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3463 fprintf(output, "[fixed] ");
3464 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3465 fprintf(output, "[default] ");
3466 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3467 fprintf(output, "[abstract] ");
3468 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3469 fprintf(output, "[nillable] ");
3470 if (elem->id != NULL)
3471 fprintf(output, "[id: '%s'] ", elem->id);
3472 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003473 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003474 /*
3475 * Default/fixed value.
3476 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003477 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003478 fprintf(output, " value: '%s'\n", elem->value);
3479 /*
3480 * Type.
3481 */
3482 if (elem->namedType != NULL) {
3483 fprintf(output, " type: %s ", elem->namedType);
3484 if (elem->namedTypeNs != NULL)
3485 fprintf(output, "ns %s\n", elem->namedTypeNs);
3486 else
3487 fprintf(output, "\n");
3488 }
3489 /*
3490 * Substitution group.
3491 */
3492 if (elem->substGroup != NULL) {
3493 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3494 if (elem->substGroupNs != NULL)
3495 fprintf(output, "ns %s\n", elem->substGroupNs);
3496 else
3497 fprintf(output, "\n");
3498 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003499}
3500
3501/**
3502 * xmlSchemaAnnotDump:
3503 * @output: the file output
3504 * @annot: a annotation
3505 *
3506 * Dump the annotation
3507 */
3508static void
3509xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3510{
3511 xmlChar *content;
3512
3513 if (annot == NULL)
3514 return;
3515
3516 content = xmlNodeGetContent(annot->content);
3517 if (content != NULL) {
3518 fprintf(output, " Annot: %s\n", content);
3519 xmlFree(content);
3520 } else
3521 fprintf(output, " Annot: empty\n");
3522}
3523
3524/**
3525 * xmlSchemaTypeDump:
3526 * @output: the file output
3527 * @type: a type structure
3528 *
3529 * Dump a SchemaType structure
3530 */
3531static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003532xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3533{
3534 xmlChar *str = NULL;
3535 xmlSchemaTreeItemPtr term;
3536 char shift[100];
3537 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003538
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003539 if (particle == NULL)
3540 return;
3541 for (i = 0;((i < depth) && (i < 25));i++)
3542 shift[2 * i] = shift[2 * i + 1] = ' ';
3543 shift[2 * i] = shift[2 * i + 1] = 0;
3544 fprintf(output, shift);
3545 if (particle->children == NULL) {
3546 fprintf(output, "MISSING particle term\n");
3547 return;
3548 }
3549 term = particle->children;
3550 switch (term->type) {
3551 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003552 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003553 ((xmlSchemaElementPtr)term)->targetNamespace,
3554 ((xmlSchemaElementPtr)term)->name));
3555 break;
3556 case XML_SCHEMA_TYPE_SEQUENCE:
3557 fprintf(output, "SEQUENCE");
3558 break;
3559 case XML_SCHEMA_TYPE_CHOICE:
3560 fprintf(output, "CHOICE");
3561 break;
3562 case XML_SCHEMA_TYPE_ALL:
3563 fprintf(output, "ALL");
3564 break;
3565 case XML_SCHEMA_TYPE_ANY:
3566 fprintf(output, "ANY");
3567 break;
3568 default:
3569 fprintf(output, "UNKNOWN\n");
3570 return;
3571 }
3572 if (particle->minOccurs != 1)
3573 fprintf(output, " min: %d", particle->minOccurs);
3574 if (particle->maxOccurs >= UNBOUNDED)
3575 fprintf(output, " max: unbounded");
3576 else if (particle->maxOccurs != 1)
3577 fprintf(output, " max: %d", particle->maxOccurs);
3578 fprintf(output, "\n");
3579 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3580 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3581 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3582 (term->children != NULL)) {
3583 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3584 output, depth +1);
3585 }
3586 if (particle->next != NULL)
3587 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3588 output, depth);
3589}
3590/**
3591 * xmlSchemaTypeDump:
3592 * @output: the file output
3593 * @type: a type structure
3594 *
3595 * Dump a SchemaType structure
3596 */
3597static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003598xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3599{
3600 if (type == NULL) {
3601 fprintf(output, "Type: NULL\n");
3602 return;
3603 }
3604 fprintf(output, "Type: ");
3605 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003606 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003607 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003608 fprintf(output, "no name ");
3609 if (type->targetNamespace != NULL)
3610 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 switch (type->type) {
3612 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003613 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 break;
3615 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003616 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003617 break;
3618 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003619 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003620 break;
3621 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003622 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 break;
3624 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003625 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003626 break;
3627 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003628 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 break;
3630 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003631 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 break;
3633 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003634 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003635 break;
3636 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003637 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 break;
3639 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003640 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003641 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003642 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003643 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003644 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003645 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003646 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003647 break;
3648 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003649 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 break;
3651 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003652 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003653 break;
3654 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003655 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003656 break;
3657 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003658 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003659 break;
3660 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003661 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003662 break;
3663 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003664 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003665 break;
3666 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003667 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003668 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003669 }
3670 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003671 if (type->base != NULL) {
3672 fprintf(output, " base type: %s", type->base);
3673 if (type->baseNs != NULL)
3674 fprintf(output, " ns %s\n", type->baseNs);
3675 else
3676 fprintf(output, "\n");
3677 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003678 if (type->annot != NULL)
3679 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003680#ifdef DUMP_CONTENT_MODEL
3681 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3682 (type->subtypes != NULL)) {
3683 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3684 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003686#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003687}
3688
3689/**
3690 * xmlSchemaDump:
3691 * @output: the file output
3692 * @schema: a schema structure
3693 *
3694 * Dump a Schema structure.
3695 */
3696void
3697xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3698{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003699 if (output == NULL)
3700 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003701 if (schema == NULL) {
3702 fprintf(output, "Schemas: NULL\n");
3703 return;
3704 }
3705 fprintf(output, "Schemas: ");
3706 if (schema->name != NULL)
3707 fprintf(output, "%s, ", schema->name);
3708 else
3709 fprintf(output, "no name, ");
3710 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003711 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003712 else
3713 fprintf(output, "no target namespace");
3714 fprintf(output, "\n");
3715 if (schema->annot != NULL)
3716 xmlSchemaAnnotDump(output, schema->annot);
3717
3718 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3719 output);
3720 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003722}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003723
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003724#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003725/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003726 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003727 * @vctxt: the WXS validation context
3728 *
3729 * Displays the current IDC table for debug purposes.
3730 */
3731static void
3732xmlSchemaDebugDumpIDCTable(FILE * output,
3733 const xmlChar *namespaceName,
3734 const xmlChar *localName,
3735 xmlSchemaPSVIIDCBindingPtr bind)
3736{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003737 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003738 xmlSchemaPSVIIDCNodePtr tab;
3739 xmlSchemaPSVIIDCKeyPtr key;
3740 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003741
3742 fprintf(output, "IDC: TABLES on %s\n",
3743 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003744 FREE_AND_NULL(str)
3745
3746 if (bind == NULL)
3747 return;
3748 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003749 fprintf(output, "IDC: BINDING %s\n",
3750 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003751 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003752 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003753 for (i = 0; i < bind->nbNodes; i++) {
3754 tab = bind->nodeTable[i];
3755 fprintf(output, " ( ");
3756 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003757 key = tab->keys[j];
3758 if ((key != NULL) && (key->val != NULL)) {
3759 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003760 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003761 fprintf(output, "\"%s\" ", value);
3762 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003763 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003764 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003765 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003766 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003767 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003768 else
3769 fprintf(output, "(key missing), ");
3770 }
3771 fprintf(output, ")\n");
3772 }
3773 bind = bind->next;
3774 } while (bind != NULL);
3775}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003776#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003777#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003778
3779/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003780 * *
3781 * Utilities *
3782 * *
3783 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003784
Daniel Veillardc0826a72004-08-10 14:17:33 +00003785/**
3786 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003787 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003788 * @name: the name of the attribute
3789 *
3790 * Seeks an attribute with a name of @name in
3791 * no namespace.
3792 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003793 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003794 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003795static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003796xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003797{
3798 xmlAttrPtr prop;
3799
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003800 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003801 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003802 prop = node->properties;
3803 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003804 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003805 return(prop);
3806 prop = prop->next;
3807 }
3808 return (NULL);
3809}
3810
3811/**
3812 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003813 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003814 * @uri: the uri
3815 * @name: the name of the attribute
3816 *
3817 * Seeks an attribute with a local name of @name and
3818 * a namespace URI of @uri.
3819 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003820 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003821 */
3822static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003823xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003824{
3825 xmlAttrPtr prop;
3826
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003827 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003828 return(NULL);
3829 prop = node->properties;
3830 while (prop != NULL) {
3831 if ((prop->ns != NULL) &&
3832 xmlStrEqual(prop->name, BAD_CAST name) &&
3833 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003834 return(prop);
3835 prop = prop->next;
3836 }
3837 return (NULL);
3838}
3839
3840static const xmlChar *
3841xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3842{
3843 xmlChar *val;
3844 const xmlChar *ret;
3845
3846 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003847 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003848 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003849 ret = xmlDictLookup(ctxt->dict, val, -1);
3850 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003851 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003852}
3853
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003854/**
3855 * xmlSchemaGetProp:
3856 * @ctxt: the parser context
3857 * @node: the node
3858 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003859 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003860 * Read a attribute value and internalize the string
3861 *
3862 * Returns the string or NULL if not present.
3863 */
3864static const xmlChar *
3865xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3866 const char *name)
3867{
3868 xmlChar *val;
3869 const xmlChar *ret;
3870
3871 val = xmlGetProp(node, BAD_CAST name);
3872 if (val == NULL)
3873 return(NULL);
3874 ret = xmlDictLookup(ctxt->dict, val, -1);
3875 xmlFree(val);
3876 return(ret);
3877}
3878
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003879/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003880 * *
3881 * Parsing functions *
3882 * *
3883 ************************************************************************/
3884
3885/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003886 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003887 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003888 * @name: the element name
3889 * @ns: the element namespace
3890 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003891 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003892 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003893 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003894 */
3895static xmlSchemaElementPtr
3896xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003897 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003898{
3899 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003900
3901 if ((name == NULL) || (schema == NULL))
3902 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003903
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003904 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003905 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003906 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003907 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003908 } else
3909 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003910 /*
3911 * This one was removed, since top level element declarations have
3912 * the target namespace specified in targetNamespace of the <schema>
3913 * information element, even if elementFormDefault is "unqualified".
3914 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003915
William M. Bracke7091952004-05-11 15:09:58 +00003916 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003917 if (xmlStrEqual(namespace, schema->targetNamespace))
3918 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3919 else
3920 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003921 if ((ret != NULL) &&
3922 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003923 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003924 }
William M. Bracke7091952004-05-11 15:09:58 +00003925 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003926
William M. Brack2f2a6632004-08-20 23:09:47 +00003927 /*
3928 * Removed since imported components will be hold by the main schema only.
3929 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003930 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003931 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003932 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003933 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003934 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003935 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003936 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3937 return (ret);
3938 } else
3939 ret = NULL;
3940 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003941 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003942#ifdef DEBUG
3943 if (ret == NULL) {
3944 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003945 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003946 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003947 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003948 namespace);
3949 }
3950#endif
3951 return (ret);
3952}
3953
3954/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003955 * xmlSchemaGetType:
3956 * @schema: the schemas context
3957 * @name: the type name
3958 * @ns: the type namespace
3959 *
3960 * Lookup a type in the schemas or the predefined types
3961 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003962 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003963 */
3964static xmlSchemaTypePtr
3965xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003966 const xmlChar * namespace)
3967{
Daniel Veillard4255d502002-04-16 15:50:10 +00003968 xmlSchemaTypePtr ret;
3969
3970 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003971 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003972 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003973 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003974 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003975 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003976 }
3977 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003978 if (ret != NULL)
3979 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003980 /*
3981 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003982 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003983 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003984 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003985 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003986 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003987 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003988 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003989 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3990 return (ret);
3991 } else
3992 ret = NULL;
3993 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003994 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003995#ifdef DEBUG
3996 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003997 if (namespace == NULL)
3998 fprintf(stderr, "Unable to lookup type %s", name);
3999 else
4000 fprintf(stderr, "Unable to lookup type %s:%s", name,
4001 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004002 }
4003#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004004 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004005}
4006
Daniel Veillard3646d642004-06-02 19:19:14 +00004007/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004008 * xmlSchemaGetAttributeDecl:
4009 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004010 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004011 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004012 *
4013 * Lookup a an attribute in the schema or imported schemas
4014 *
4015 * Returns the attribute declaration or NULL if not found.
4016 */
4017static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004018xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004019 const xmlChar * namespace)
4020{
4021 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004022
4023 if ((name == NULL) || (schema == NULL))
4024 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004025
4026
Daniel Veillard3646d642004-06-02 19:19:14 +00004027 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4028 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004029 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004030 else
4031 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004032 /*
4033 * Removed, since imported components will be hold by the main schema only.
4034 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004035 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004036 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004037 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004038 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004039 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004040 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004041 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4042 return (ret);
4043 } else
4044 ret = NULL;
4045 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004046 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004047#ifdef DEBUG
4048 if (ret == NULL) {
4049 if (namespace == NULL)
4050 fprintf(stderr, "Unable to lookup attribute %s", name);
4051 else
4052 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4053 namespace);
4054 }
4055#endif
4056 return (ret);
4057}
4058
4059/**
4060 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004061 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004062 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004063 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004064 *
4065 * Lookup a an attribute group in the schema or imported schemas
4066 *
4067 * Returns the attribute group definition or NULL if not found.
4068 */
4069static xmlSchemaAttributeGroupPtr
4070xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4071 const xmlChar * namespace)
4072{
4073 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004074
4075 if ((name == NULL) || (schema == NULL))
4076 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004077
4078
Daniel Veillard3646d642004-06-02 19:19:14 +00004079 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4080 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004081 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004082 else
4083 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004084 /*
4085 * Removed since imported components will be hold by the main schema only.
4086 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004087 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004088 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004089 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004090 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004091 if (import != NULL) {
4092 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4093 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4094 return (ret);
4095 else
4096 ret = NULL;
4097 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004098 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004099#ifdef DEBUG
4100 if (ret == NULL) {
4101 if (namespace == NULL)
4102 fprintf(stderr, "Unable to lookup attribute group %s", name);
4103 else
4104 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4105 namespace);
4106 }
4107#endif
4108 return (ret);
4109}
4110
4111/**
4112 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004113 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004114 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004115 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004116 *
4117 * Lookup a group in the schema or imported schemas
4118 *
4119 * Returns the group definition or NULL if not found.
4120 */
4121static xmlSchemaTypePtr
4122xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4123 const xmlChar * namespace)
4124{
4125 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004126
4127 if ((name == NULL) || (schema == NULL))
4128 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004129
Daniel Veillard3646d642004-06-02 19:19:14 +00004130 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004131 /*
4132 * Removed since imported components will be hold by the main schema only.
4133 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004134 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004135 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004136 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004137 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004138 if (import != NULL) {
4139 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4140 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4141 return (ret);
4142 else
4143 ret = NULL;
4144 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004145 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004146#ifdef DEBUG
4147 if (ret == NULL) {
4148 if (namespace == NULL)
4149 fprintf(stderr, "Unable to lookup group %s", name);
4150 else
4151 fprintf(stderr, "Unable to lookup group %s:%s", name,
4152 namespace);
4153 }
4154#endif
4155 return (ret);
4156}
4157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004158/**
4159 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004160 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004161 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004162 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004163 *
4164 * Lookup a group in the schema or imported schemas
4165 *
4166 * Returns the group definition or NULL if not found.
4167 */
4168static xmlSchemaTreeItemPtr
4169xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4170 xmlSchemaTypeType itemType,
4171 const xmlChar *name,
4172 const xmlChar *targetNs)
4173{
4174 switch (itemType) {
4175 case XML_SCHEMA_TYPE_GROUP:
4176 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4177 name, targetNs));
4178 case XML_SCHEMA_TYPE_ELEMENT:
4179 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4180 name, targetNs));
4181 default:
4182 return (NULL);
4183 }
4184}
4185
Daniel Veillard4255d502002-04-16 15:50:10 +00004186/************************************************************************
4187 * *
4188 * Parsing functions *
4189 * *
4190 ************************************************************************/
4191
4192#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004193 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004194
4195/**
4196 * xmlSchemaIsBlank:
4197 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004198 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004199 *
4200 * Check if a string is ignorable
4201 *
4202 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4203 */
4204static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004205xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004206{
Daniel Veillard4255d502002-04-16 15:50:10 +00004207 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004208 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004209 if (len < 0) {
4210 while (*str != 0) {
4211 if (!(IS_BLANK_CH(*str)))
4212 return (0);
4213 str++;
4214 }
4215 } else while ((*str != 0) && (len != 0)) {
4216 if (!(IS_BLANK_CH(*str)))
4217 return (0);
4218 str++;
4219 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004220 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004221
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004222 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004223}
4224
4225/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004226 * xmlSchemaAddAssembledItem:
4227 * @ctxt: a schema parser context
4228 * @schema: the schema being built
4229 * @item: the item
4230 *
4231 * Add a item to the schema's list of current items.
4232 * This is used if the schema was already constructed and
4233 * new schemata need to be added to it.
4234 * *WARNING* this interface is highly subject to change.
4235 *
4236 * Returns 0 if suceeds and -1 if an internal error occurs.
4237 */
4238static int
4239xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4240 xmlSchemaTypePtr item)
4241{
4242 static int growSize = 100;
4243 xmlSchemaAssemblePtr ass;
4244
4245 ass = ctxt->assemble;
4246 if (ass->sizeItems < 0) {
4247 /* If disabled. */
4248 return (0);
4249 }
4250 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004251 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004252 if (ass->items == NULL) {
4253 xmlSchemaPErrMemory(ctxt,
4254 "allocating new item buffer", NULL);
4255 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004256 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004257 ass->sizeItems = growSize;
4258 } else if (ass->sizeItems <= ass->nbItems) {
4259 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004260 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004261 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4262 if (ass->items == NULL) {
4263 xmlSchemaPErrMemory(ctxt,
4264 "growing item buffer", NULL);
4265 ass->sizeItems = 0;
4266 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004267 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004268 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004269 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004270 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4271 return (0);
4272}
4273
4274/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004275 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004276 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004277 * @schema: the schema being built
4278 * @name: the item name
4279 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004280 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004281 * *WARNING* this interface is highly subject to change
4282 *
4283 * Returns the new struture or NULL in case of error
4284 */
4285static xmlSchemaNotationPtr
4286xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004287 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004288{
4289 xmlSchemaNotationPtr ret = NULL;
4290 int val;
4291
4292 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4293 return (NULL);
4294
4295 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004296 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 if (schema->notaDecl == NULL)
4298 return (NULL);
4299
4300 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4301 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004302 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004303 return (NULL);
4304 }
4305 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004306 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4308 ret);
4309 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004310 /*
4311 * TODO: This should never happen, since a unique name will be computed.
4312 * If it fails, then an other internal error must have occured.
4313 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004314 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4315 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004316 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004317 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004318 xmlFree(ret);
4319 return (NULL);
4320 }
4321 return (ret);
4322}
4323
4324
4325/**
4326 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004327 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 * @schema: the schema being built
4329 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004330 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004331 *
4332 * Add an XML schema Attrribute declaration
4333 * *WARNING* this interface is highly subject to change
4334 *
4335 * Returns the new struture or NULL in case of error
4336 */
4337static xmlSchemaAttributePtr
4338xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004339 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004340 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004341{
4342 xmlSchemaAttributePtr ret = NULL;
4343 int val;
4344
4345 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4346 return (NULL);
4347
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004348#ifdef DEBUG
4349 fprintf(stderr, "Adding attribute %s\n", name);
4350 if (namespace != NULL)
4351 fprintf(stderr, " target namespace %s\n", namespace);
4352#endif
4353
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004355 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004356 if (schema->attrDecl == NULL)
4357 return (NULL);
4358
4359 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4360 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004361 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004362 return (NULL);
4363 }
4364 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004365 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004366 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004367 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004368 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004369 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004370 if (topLevel) {
4371 xmlSchemaPCustomErr(ctxt,
4372 XML_SCHEMAP_REDEFINED_ATTR,
4373 NULL, NULL, node,
4374 "A global attribute declaration with the name '%s' does "
4375 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004376 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004377 return (NULL);
4378 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004379 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004380 /*
4381 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4382 * in the scenario:
4383 * 1. multiple top-level complex types have different target
4384 * namespaces but have the SAME NAME; this can happen if
4385 * schemata are imported
4386 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004387 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004388 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004389 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004390 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004391 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004392 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004393
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004394 if (val != 0) {
4395 xmlSchemaPCustomErr(ctxt,
4396 XML_SCHEMAP_INTERNAL,
4397 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004398 "Internal error: xmlSchemaAddAttribute, "
4399 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004400 "could not be added to the hash.", name);
4401 xmlFree(ret);
4402 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004403 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004404 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004405 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004406 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004407 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004408 return (ret);
4409}
4410
4411/**
4412 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004413 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004414 * @schema: the schema being built
4415 * @name: the item name
4416 *
4417 * Add an XML schema Attrribute Group declaration
4418 *
4419 * Returns the new struture or NULL in case of error
4420 */
4421static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004422xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004423 xmlSchemaPtr schema, const xmlChar * name,
4424 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004425{
4426 xmlSchemaAttributeGroupPtr ret = NULL;
4427 int val;
4428
4429 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4430 return (NULL);
4431
4432 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004433 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004434 if (schema->attrgrpDecl == NULL)
4435 return (NULL);
4436
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004437 ret =
4438 (xmlSchemaAttributeGroupPtr)
4439 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004441 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004442 return (NULL);
4443 }
4444 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004445 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004447 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004448 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004449 xmlSchemaPCustomErr(ctxt,
4450 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4451 NULL, NULL, node,
4452 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004453 xmlFree(ret);
4454 return (NULL);
4455 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004456 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004457 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 return (ret);
4459}
4460
4461/**
4462 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004463 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004464 * @schema: the schema being built
4465 * @name: the type name
4466 * @namespace: the type namespace
4467 *
4468 * Add an XML schema Element declaration
4469 * *WARNING* this interface is highly subject to change
4470 *
4471 * Returns the new struture or NULL in case of error
4472 */
4473static xmlSchemaElementPtr
4474xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004475 const xmlChar * name, const xmlChar * namespace,
4476 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004477{
4478 xmlSchemaElementPtr ret = NULL;
4479 int val;
4480
4481 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4482 return (NULL);
4483
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004484#ifdef DEBUG
4485 fprintf(stderr, "Adding element %s\n", name);
4486 if (namespace != NULL)
4487 fprintf(stderr, " target namespace %s\n", namespace);
4488#endif
4489
Daniel Veillard4255d502002-04-16 15:50:10 +00004490 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004491 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004492 if (schema->elemDecl == NULL)
4493 return (NULL);
4494
4495 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4496 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004497 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004498 return (NULL);
4499 }
4500 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004501 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004504 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004505 if (topLevel) {
4506 xmlSchemaPCustomErr(ctxt,
4507 XML_SCHEMAP_REDEFINED_ELEMENT,
4508 NULL, NULL, node,
4509 "A global element declaration with the name '%s' does "
4510 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004511 xmlFree(ret);
4512 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004513 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004514 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004515
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004516 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004517 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004518 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004519 if (val != 0) {
4520 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004521 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004522 NULL, NULL, node,
4523 "Internal error: xmlSchemaAddElement, "
4524 "a dublicate element declaration with the name '%s' "
4525 "could not be added to the hash.", name);
4526 xmlFree(ret);
4527 return (NULL);
4528 }
4529 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004530
Daniel Veillard4255d502002-04-16 15:50:10 +00004531 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004532 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004533 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004534 return (ret);
4535}
4536
4537/**
4538 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004539 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004540 * @schema: the schema being built
4541 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004542 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004543 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004544 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004545 * *WARNING* this interface is highly subject to change
4546 *
4547 * Returns the new struture or NULL in case of error
4548 */
4549static xmlSchemaTypePtr
4550xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004551 const xmlChar * name, const xmlChar * namespace,
4552 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004553{
4554 xmlSchemaTypePtr ret = NULL;
4555 int val;
4556
4557 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4558 return (NULL);
4559
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004560#ifdef DEBUG
4561 fprintf(stderr, "Adding type %s\n", name);
4562 if (namespace != NULL)
4563 fprintf(stderr, " target namespace %s\n", namespace);
4564#endif
4565
Daniel Veillard4255d502002-04-16 15:50:10 +00004566 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004567 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004568 if (schema->typeDecl == NULL)
4569 return (NULL);
4570
4571 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4572 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004573 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004574 return (NULL);
4575 }
4576 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004577 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004578 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004579 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004580 if (val != 0) {
4581 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004582 xmlSchemaPCustomErr(ctxt,
4583 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004584 NULL, NULL, node,
4585 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004586 xmlFree(ret);
4587 return (NULL);
4588 } else {
4589 xmlSchemaTypePtr prev;
4590
4591 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4592 if (prev == NULL) {
4593 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004594 XML_ERR_INTERNAL_ERROR,
4595 "Internal error: xmlSchemaAddType, on type "
4596 "'%s'.\n",
4597 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004598 xmlFree(ret);
4599 return (NULL);
4600 }
4601 ret->redef = prev->redef;
4602 prev->redef = ret;
4603 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004604 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004605 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004606 ret->minOccurs = 1;
4607 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004608 ret->attributeUses = NULL;
4609 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004610 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004611 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004612 return (ret);
4613}
4614
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004615static xmlSchemaQNameRefPtr
4616xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4617 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004618 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004619 const xmlChar *refNs)
4620{
4621 xmlSchemaQNameRefPtr ret;
4622
4623 ret = (xmlSchemaQNameRefPtr)
4624 xmlMalloc(sizeof(xmlSchemaQNameRef));
4625 if (ret == NULL) {
4626 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4627 NULL);
4628 return (NULL);
4629 }
4630 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4631 ret->name = refName;
4632 ret->targetNamespace = refNs;
4633 ret->item = NULL;
4634 ret->itemType = refType;
4635 /*
4636 * Store the reference item in the schema.
4637 */
4638 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4639 return (ret);
4640}
4641
4642/**
4643 * xmlSchemaAddModelGroup:
4644 * @ctxt: a schema parser context
4645 * @schema: the schema being built
4646 * @type: the "compositor" type of the model group
4647 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004648 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004649 *
4650 * Adds a schema model group
4651 * *WARNING* this interface is highly subject to change
4652 *
4653 * Returns the new struture or NULL in case of error
4654 */
4655static xmlSchemaModelGroupPtr
4656xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4657 xmlSchemaTypeType type, const xmlChar **container,
4658 xmlNodePtr node)
4659{
4660 xmlSchemaModelGroupPtr ret = NULL;
4661 xmlChar buf[30];
4662
4663 if ((ctxt == NULL) || (schema == NULL))
4664 return (NULL);
4665
4666#ifdef DEBUG
4667 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004668#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004669 ret = (xmlSchemaModelGroupPtr)
4670 xmlMalloc(sizeof(xmlSchemaModelGroup));
4671 if (ret == NULL) {
4672 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4673 NULL);
4674 return (NULL);
4675 }
4676 ret->type = type;
4677 ret->annot = NULL;
4678 ret->node = node;
4679 ret->children = NULL;
4680 ret->next = NULL;
4681 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4682 if (container != NULL)
4683 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4684 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004685 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004686 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4687 } else {
4688 if (container != NULL)
4689 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4690 }
4691 if (container != NULL)
4692 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4693 /*
4694 * Add to volatile items.
4695 * TODO: this should be changed someday.
4696 */
4697 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4698 xmlFree(ret);
4699 return (NULL);
4700 }
4701 return (ret);
4702}
4703
4704
4705/**
4706 * xmlSchemaAddParticle:
4707 * @ctxt: a schema parser context
4708 * @schema: the schema being built
4709 * @node: the corresponding node in the schema doc
4710 * @min: the minOccurs
4711 * @max: the maxOccurs
4712 *
4713 * Adds an XML schema particle component.
4714 * *WARNING* this interface is highly subject to change
4715 *
4716 * Returns the new struture or NULL in case of error
4717 */
4718static xmlSchemaParticlePtr
4719xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4720 xmlNodePtr node, int min, int max)
4721{
4722 xmlSchemaParticlePtr ret = NULL;
4723 if ((ctxt == NULL) || (schema == NULL))
4724 return (NULL);
4725
4726#ifdef DEBUG
4727 fprintf(stderr, "Adding particle component\n");
4728#endif
4729 ret = (xmlSchemaParticlePtr)
4730 xmlMalloc(sizeof(xmlSchemaParticle));
4731 if (ret == NULL) {
4732 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4733 NULL);
4734 return (NULL);
4735 }
4736 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4737 ret->annot = NULL;
4738 ret->node = node;
4739 ret->minOccurs = min;
4740 ret->maxOccurs = max;
4741 ret->next = NULL;
4742 ret->children = NULL;
4743
4744 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4745 xmlFree(ret);
4746 return (NULL);
4747 }
4748 return (ret);
4749}
4750
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004751/**
4752 * xmlSchemaAddGroup:
4753 * @ctxt: a schema validation context
4754 * @schema: the schema being built
4755 * @name: the group name
4756 *
4757 * Add an XML schema Group definition
4758 *
4759 * Returns the new struture or NULL in case of error
4760 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004761static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004762xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004763 const xmlChar *name, const xmlChar *namespaceName,
4764 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004766 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004767 int val;
4768
4769 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4770 return (NULL);
4771
4772 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004773 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004774 if (schema->groupDecl == NULL)
4775 return (NULL);
4776
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004777 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004778 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004779 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004780 return (NULL);
4781 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004782 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004783 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004784 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004785 ret->node = node;
4786 ret->targetNamespace = namespaceName;
4787 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004788 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004789 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004790 XML_SCHEMAP_REDEFINED_GROUP,
4791 NULL, NULL, node,
4792 "A global model group definition with the name '%s' does already "
4793 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004794 xmlFree(ret);
4795 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004796 }
4797 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004798 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004799 return (ret);
4800}
4801
Daniel Veillard3646d642004-06-02 19:19:14 +00004802/**
4803 * xmlSchemaNewWildcardNs:
4804 * @ctxt: a schema validation context
4805 *
4806 * Creates a new wildcard namespace constraint.
4807 *
4808 * Returns the new struture or NULL in case of error
4809 */
4810static xmlSchemaWildcardNsPtr
4811xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4812{
4813 xmlSchemaWildcardNsPtr ret;
4814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004815 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004816 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4817 if (ret == NULL) {
4818 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004819 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004820 }
4821 ret->value = NULL;
4822 ret->next = NULL;
4823 return (ret);
4824}
4825
4826/**
4827 * xmlSchemaAddWildcard:
4828 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004829 * @schema: a schema
4830 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004831 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004832 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004833 *
4834 * Returns the new struture or NULL in case of error
4835 */
4836static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004837xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4838 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004839{
4840 xmlSchemaWildcardPtr ret = NULL;
4841
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004842 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004843 return (NULL);
4844
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004845#ifdef DEBUG
4846 fprintf(stderr, "Adding wildcard component\n");
4847#endif
4848
Daniel Veillard3646d642004-06-02 19:19:14 +00004849 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4850 if (ret == NULL) {
4851 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4852 return (NULL);
4853 }
4854 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004855 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004856 ret->minOccurs = 1;
4857 ret->maxOccurs = 1;
4858
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004859 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4860 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4861 "Failed to add a wildcard component to the list", NULL);
4862 xmlFree(ret);
4863 return (NULL);
4864 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004865 return (ret);
4866}
4867
Daniel Veillard4255d502002-04-16 15:50:10 +00004868/************************************************************************
4869 * *
4870 * Utilities for parsing *
4871 * *
4872 ************************************************************************/
4873
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004874#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004875/**
4876 * xmlGetQNameProp:
4877 * @ctxt: a schema validation context
4878 * @node: a subtree containing XML Schema informations
4879 * @name: the attribute name
4880 * @namespace: the result namespace if any
4881 *
4882 * Extract a QName Attribute value
4883 *
4884 * Returns the NCName or NULL if not found, and also update @namespace
4885 * with the namespace URI
4886 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004887static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004888xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004889 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004890{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004891 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004892 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004893 const xmlChar *ret, *prefix;
4894 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004895 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004896
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004897 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004898 attr = xmlSchemaGetPropNode(node, name);
4899 if (attr == NULL)
4900 return (NULL);
4901 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004902
Daniel Veillard4255d502002-04-16 15:50:10 +00004903 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004904 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004905
Daniel Veillardba0153a2004-04-01 10:42:31 +00004906 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004907 ns = xmlSearchNs(node->doc, node, 0);
4908 if (ns) {
4909 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4910 return (val);
4911 }
4912 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004913 ret = xmlSplitQName3(val, &len);
4914 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004915 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004916 }
4917 ret = xmlDictLookup(ctxt->dict, ret, -1);
4918 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004919
4920 ns = xmlSearchNs(node->doc, node, prefix);
4921 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004922 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4923 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004924 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004925 "The QName value '%s' has no corresponding namespace "
4926 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004927 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004928 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004929 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004930 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004931}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004932#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004933
4934/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004935 * xmlSchemaPValAttrNodeQNameValue:
4936 * @ctxt: a schema parser context
4937 * @schema: the schema context
4938 * @ownerDes: the designation of the parent element
4939 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004940 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004941 * @local: the resulting local part if found, the attribute value otherwise
4942 * @uri: the resulting namespace URI if found
4943 *
4944 * Extracts the local name and the URI of a QName value and validates it.
4945 * This one is intended to be used on attribute values that
4946 * should resolve to schema components.
4947 *
4948 * Returns 0, in case the QName is valid, a positive error code
4949 * if not valid and -1 if an internal error occurs.
4950 */
4951static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004952xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004953 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004954 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004955 xmlSchemaTypePtr ownerItem,
4956 xmlAttrPtr attr,
4957 const xmlChar *value,
4958 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004959 const xmlChar **local)
4960{
4961 const xmlChar *pref;
4962 xmlNsPtr ns;
4963 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004964
Daniel Veillardc0826a72004-08-10 14:17:33 +00004965 *uri = NULL;
4966 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004967 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004968 if (ret > 0) {
4969 xmlSchemaPSimpleTypeErr(ctxt,
4970 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4971 ownerItem, (xmlNodePtr) attr,
4972 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4973 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004974 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004975 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004976 } else if (ret < 0)
4977 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004978
4979 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004980 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4981 if (ns)
4982 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4983 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4984 /*
4985 * This one takes care of included schemas with no
4986 * target namespace.
4987 */
4988 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004989 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004990 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 return (0);
4992 }
4993 /*
4994 * At this point xmlSplitQName3 has to return a local name.
4995 */
4996 *local = xmlSplitQName3(value, &len);
4997 *local = xmlDictLookup(ctxt->dict, *local, -1);
4998 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004999 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5000 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005001 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005002 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005003 ownerItem, (xmlNodePtr) attr,
5004 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5005 "The value '%s' of simple type 'xs:QName' has no "
5006 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005007 return (ctxt->err);
5008 } else {
5009 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005010 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005011 return (0);
5012}
5013
5014/**
5015 * xmlSchemaPValAttrNodeQName:
5016 * @ctxt: a schema parser context
5017 * @schema: the schema context
5018 * @ownerDes: the designation of the owner element
5019 * @ownerItem: the owner as a schema object
5020 * @attr: the attribute node
5021 * @local: the resulting local part if found, the attribute value otherwise
5022 * @uri: the resulting namespace URI if found
5023 *
5024 * Extracts and validates the QName of an attribute value.
5025 * This one is intended to be used on attribute values that
5026 * should resolve to schema components.
5027 *
5028 * Returns 0, in case the QName is valid, a positive error code
5029 * if not valid and -1 if an internal error occurs.
5030 */
5031static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005032xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005033 xmlSchemaPtr schema,
5034 xmlChar **ownerDes,
5035 xmlSchemaTypePtr ownerItem,
5036 xmlAttrPtr attr,
5037 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005038 const xmlChar **local)
5039{
5040 const xmlChar *value;
5041
5042 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005043 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5044 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005045}
5046
5047/**
5048 * xmlSchemaPValAttrQName:
5049 * @ctxt: a schema parser context
5050 * @schema: the schema context
5051 * @ownerDes: the designation of the parent element
5052 * @ownerItem: the owner as a schema object
5053 * @ownerElem: the parent node of the attribute
5054 * @name: the name of the attribute
5055 * @local: the resulting local part if found, the attribute value otherwise
5056 * @uri: the resulting namespace URI if found
5057 *
5058 * Extracts and validates the QName of an attribute value.
5059 *
5060 * Returns 0, in case the QName is valid, a positive error code
5061 * if not valid and -1 if an internal error occurs.
5062 */
5063static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005064xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5065 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005066 xmlChar **ownerDes,
5067 xmlSchemaTypePtr ownerItem,
5068 xmlNodePtr ownerElem,
5069 const char *name,
5070 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005071 const xmlChar **local)
5072{
5073 xmlAttrPtr attr;
5074
5075 attr = xmlSchemaGetPropNode(ownerElem, name);
5076 if (attr == NULL) {
5077 *local = NULL;
5078 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005079 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005080 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005081 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5082 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005083}
5084
5085/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005086 * xmlSchemaPValAttrID:
5087 * @ctxt: a schema parser context
5088 * @schema: the schema context
5089 * @ownerDes: the designation of the parent element
5090 * @ownerItem: the owner as a schema object
5091 * @ownerElem: the parent node of the attribute
5092 * @name: the name of the attribute
5093 *
5094 * Extracts and validates the ID of an attribute value.
5095 *
5096 * Returns 0, in case the ID is valid, a positive error code
5097 * if not valid and -1 if an internal error occurs.
5098 */
5099static int
5100xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005101 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005102 xmlSchemaTypePtr ownerItem,
5103 xmlNodePtr ownerElem,
5104 const xmlChar *name)
5105{
5106 int ret;
5107 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005108 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005109
5110 value = xmlGetNoNsProp(ownerElem, name);
5111 if (value == NULL)
5112 return (0);
5113
5114 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5115 if (attr == NULL)
5116 return (-1);
5117
5118 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005119 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005120 /*
5121 * NOTE: the IDness might have already be declared in the DTD
5122 */
5123 if (attr->atype != XML_ATTRIBUTE_ID) {
5124 xmlIDPtr res;
5125 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005126
5127 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005128 * TODO: Use xmlSchemaStrip here; it's not exported at this
5129 * moment.
5130 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005131 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005132 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005133 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005134 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5135 if (res == NULL) {
5136 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005137 xmlSchemaPSimpleTypeErr(ctxt,
5138 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5139 ownerItem, (xmlNodePtr) attr,
5140 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5141 NULL, NULL, "Duplicate value '%s' of simple "
5142 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005143 } else
5144 attr->atype = XML_ATTRIBUTE_ID;
5145 if (strip != NULL)
5146 xmlFree(strip);
5147 }
5148 } else if (ret > 0) {
5149 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005150 xmlSchemaPSimpleTypeErr(ctxt,
5151 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5152 ownerItem, (xmlNodePtr) attr,
5153 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5154 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5155 "not a valid 'xs:NCName'",
5156 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005157 }
5158 xmlFree(value);
5159
5160 return (ret);
5161}
5162
5163/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005164 * xmlGetMaxOccurs:
5165 * @ctxt: a schema validation context
5166 * @node: a subtree containing XML Schema informations
5167 *
5168 * Get the maxOccurs property
5169 *
5170 * Returns the default if not found, or the value
5171 */
5172static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005173xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5174 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005175{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005176 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005177 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005178 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005179
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005180 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5181 if (attr == NULL)
5182 return (def);
5183 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005184
5185 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005186 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005187 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005188 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5189 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005190 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005191 val, NULL, NULL, NULL);
5192 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005193 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005194 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005195 }
5196
5197 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005198 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005199 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005200 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005201 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005202 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5203 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005204 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005205 val, NULL, NULL, NULL);
5206 return (def);
5207 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005208 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005209 ret = ret * 10 + (*cur - '0');
5210 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005211 }
William M. Brack76e95df2003-10-18 16:20:14 +00005212 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005213 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005214 /*
5215 * TODO: Restrict the maximal value to Integer.
5216 */
5217 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005218 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005219 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5220 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005221 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005222 val, NULL, NULL, NULL);
5223 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005224 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005225 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005226}
5227
5228/**
5229 * xmlGetMinOccurs:
5230 * @ctxt: a schema validation context
5231 * @node: a subtree containing XML Schema informations
5232 *
5233 * Get the minOccurs property
5234 *
5235 * Returns the default if not found, or the value
5236 */
5237static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005238xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005239 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005240{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005241 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005242 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005243 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005244
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005245 attr = xmlSchemaGetPropNode(node, "minOccurs");
5246 if (attr == NULL)
5247 return (def);
5248 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005250 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005251 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005252 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005253 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005254 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5255 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005256 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005257 val, NULL, NULL, NULL);
5258 return (def);
5259 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005260 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 ret = ret * 10 + (*cur - '0');
5262 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005263 }
William M. Brack76e95df2003-10-18 16:20:14 +00005264 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005265 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005266 /*
5267 * TODO: Restrict the maximal value to Integer.
5268 */
5269 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005270 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005271 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5272 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005273 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005274 val, NULL, NULL, NULL);
5275 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005276 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005277 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005278}
5279
5280/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005281 * xmlSchemaPGetBoolNodeValue:
5282 * @ctxt: a schema validation context
5283 * @ownerDes: owner designation
5284 * @ownerItem: the owner as a schema item
5285 * @node: the node holding the value
5286 *
5287 * Converts a boolean string value into 1 or 0.
5288 *
5289 * Returns 0 or 1.
5290 */
5291static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005292xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5293 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005294 xmlSchemaTypePtr ownerItem,
5295 xmlNodePtr node)
5296{
5297 xmlChar *value = NULL;
5298 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005299
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005300 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005301 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005302 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005303 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005304 * can have the following legal literals {true, false, 1, 0}.
5305 */
5306 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5307 res = 1;
5308 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5309 res = 0;
5310 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5311 res = 1;
5312 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005313 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005314 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005315 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005316 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005317 ownerItem, node,
5318 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5319 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005320 NULL, NULL, NULL);
5321 }
5322 if (value != NULL)
5323 xmlFree(value);
5324 return (res);
5325}
5326
5327/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005328 * xmlGetBooleanProp:
5329 * @ctxt: a schema validation context
5330 * @node: a subtree containing XML Schema informations
5331 * @name: the attribute name
5332 * @def: the default value
5333 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005334 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005335 *
5336 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005337 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 */
5339static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005340xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5341 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005342 xmlSchemaTypePtr ownerItem,
5343 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005344 const char *name, int def)
5345{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005346 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005347
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005348 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005349 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005350 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005351 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005353 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005354 * can have the following legal literals {true, false, 1, 0}.
5355 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005356 if (xmlStrEqual(val, BAD_CAST "true"))
5357 def = 1;
5358 else if (xmlStrEqual(val, BAD_CAST "false"))
5359 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005360 else if (xmlStrEqual(val, BAD_CAST "1"))
5361 def = 1;
5362 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005363 def = 0;
5364 else {
5365 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005366 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005367 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005368 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005369 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5370 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005371 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005372 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005373}
5374
5375/************************************************************************
5376 * *
5377 * Shema extraction from an Infoset *
5378 * *
5379 ************************************************************************/
5380static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5381 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005382 xmlNodePtr node,
5383 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005384static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5385 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005386 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005387 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005388 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005389static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5390 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005391 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005392 xmlNodePtr node,
5393 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005394static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5395 ctxt,
5396 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005397 xmlNodePtr node,
5398 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005399static xmlSchemaAttributeGroupPtr
5400xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005401 xmlSchemaPtr schema, xmlNodePtr node,
5402 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005403static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5404 xmlSchemaPtr schema,
5405 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005406static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005407xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5408 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005409
5410/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005411 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005412 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005413 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005414 * @ownerDes: the designation of the parent element
5415 * @ownerItem: the schema object owner if existent
5416 * @attr: the schema attribute node being validated
5417 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005418 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005419 *
5420 * Validates a value against the given built-in type.
5421 * This one is intended to be used internally for validation
5422 * of schema attribute values during parsing of the schema.
5423 *
5424 * Returns 0 if the value is valid, a positive error code
5425 * number otherwise and -1 in case of an internal or API error.
5426 */
5427static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005428xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5429 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5430 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005431 xmlAttrPtr attr,
5432 const xmlChar *value,
5433 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005434{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005435
5436 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005437
5438 /*
5439 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5440 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005441 */
5442 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005443 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005444 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5445 PERROR_INT("xmlSchemaPValAttrNodeValue",
5446 "the given type is not a built-in type");
5447 return (-1);
5448 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005449 switch (type->builtInType) {
5450 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005451 case XML_SCHEMAS_QNAME:
5452 case XML_SCHEMAS_ANYURI:
5453 case XML_SCHEMAS_TOKEN:
5454 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005455 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5456 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005457 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005458 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005459 PERROR_INT("xmlSchemaPValAttrNodeValue",
5460 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005461 return (-1);
5462 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005463 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005464 /*
5465 * TODO: Should we use the S4S error codes instead?
5466 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005467 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005468 PERROR_INT("xmlSchemaPValAttrNodeValue",
5469 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005470 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005471 } else if (ret > 0) {
5472 if (VARIETY_LIST(type))
5473 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5474 else
5475 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5476 xmlSchemaPSimpleTypeErr(pctxt,
5477 ret, ownerItem, (xmlNodePtr) attr,
5478 type, NULL, value, NULL, NULL, NULL);
5479 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005480 return (ret);
5481}
5482
5483/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005484 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005485 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005486 * @ctxt: a schema parser context
5487 * @ownerDes: the designation of the parent element
5488 * @ownerItem: the schema object owner if existent
5489 * @attr: the schema attribute node being validated
5490 * @type: the built-in type to be validated against
5491 * @value: the resulting value if any
5492 *
5493 * Extracts and validates a value against the given built-in type.
5494 * This one is intended to be used internally for validation
5495 * of schema attribute values during parsing of the schema.
5496 *
5497 * Returns 0 if the value is valid, a positive error code
5498 * number otherwise and -1 in case of an internal or API error.
5499 */
5500static int
5501xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5502 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005503 xmlSchemaTypePtr ownerItem,
5504 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005505 xmlSchemaTypePtr type,
5506 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005507{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005508 const xmlChar *val;
5509
5510 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005511 return (-1);
5512
Daniel Veillardc0826a72004-08-10 14:17:33 +00005513 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5514 if (value != NULL)
5515 *value = val;
5516
5517 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005518 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005519}
5520
5521/**
5522 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005523 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005524 * @ctxt: a schema parser context
5525 * @node: the element node of the attribute
5526 * @ownerDes: the designation of the parent element
5527 * @ownerItem: the schema object owner if existent
5528 * @ownerElem: the owner element node
5529 * @name: the name of the schema attribute node
5530 * @type: the built-in type to be validated against
5531 * @value: the resulting value if any
5532 *
5533 * Extracts and validates a value against the given built-in type.
5534 * This one is intended to be used internally for validation
5535 * of schema attribute values during parsing of the schema.
5536 *
5537 * Returns 0 if the value is valid, a positive error code
5538 * number otherwise and -1 in case of an internal or API error.
5539 */
5540static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005541xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005542 xmlChar **ownerDes,
5543 xmlSchemaTypePtr ownerItem,
5544 xmlNodePtr ownerElem,
5545 const char *name,
5546 xmlSchemaTypePtr type,
5547 const xmlChar **value)
5548{
5549 xmlAttrPtr attr;
5550
5551 if ((ctxt == NULL) || (type == NULL)) {
5552 if (value != NULL)
5553 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005554 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005555 }
5556 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5557 if (value != NULL)
5558 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005559 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005560 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 "Internal error: xmlSchemaPValAttr, the given "
5562 "type '%s' is not a built-in type.\n",
5563 type->name, NULL);
5564 return (-1);
5565 }
5566 attr = xmlSchemaGetPropNode(ownerElem, name);
5567 if (attr == NULL) {
5568 if (value != NULL)
5569 *value = NULL;
5570 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005571 }
5572 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005573 type, value));
5574}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005575
5576static int
5577xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5578 xmlSchemaPtr schema,
5579 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005580 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005581 const xmlChar *namespaceName)
5582{
5583 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005584 return (1);
5585 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5586 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005587 if (pctxt->localImports != NULL) {
5588 int i;
5589 for (i = 0; i < pctxt->nbLocalImports; i++)
5590 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5591 return (1);
5592 }
5593 if (namespaceName == NULL)
5594 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005595 NULL, (xmlSchemaTypePtr) item, node,
5596 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005597 "namespace are not valid, since not indicated by an import "
5598 "statement", NULL);
5599 else
5600 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005601 NULL, (xmlSchemaTypePtr) item, node,
5602 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005603 "namespace '%s' are not valid, since not indicated by an import "
5604 "statement", namespaceName);
5605 return (0);
5606}
5607
Daniel Veillardc0826a72004-08-10 14:17:33 +00005608/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 * xmlSchemaParseAttrDecls:
5610 * @ctxt: a schema validation context
5611 * @schema: the schema being built
5612 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005613 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005614 *
5615 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005616 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005617 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5618 */
5619static xmlNodePtr
5620xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5621 xmlNodePtr child, xmlSchemaTypePtr type)
5622{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005623 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005624
Daniel Veillard4255d502002-04-16 15:50:10 +00005625 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626 (IS_SCHEMA(child, "attributeGroup"))) {
5627 attr = NULL;
5628 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005629 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005630 } else if (IS_SCHEMA(child, "attributeGroup")) {
5631 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005632 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005633 }
5634 if (attr != NULL) {
5635 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005636 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5637 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5638 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005639 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005640 lastattr = attr;
5641 } else {
5642 lastattr->next = attr;
5643 lastattr = attr;
5644 }
5645 }
5646 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005647 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005648 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005649}
5650
5651/**
5652 * xmlSchemaParseAnnotation:
5653 * @ctxt: a schema validation context
5654 * @schema: the schema being built
5655 * @node: a subtree containing XML Schema informations
5656 *
5657 * parse a XML schema Attrribute declaration
5658 * *WARNING* this interface is highly subject to change
5659 *
William M. Bracke7091952004-05-11 15:09:58 +00005660 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 * 1 in case of success.
5662 */
5663static xmlSchemaAnnotPtr
5664xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5665 xmlNodePtr node)
5666{
5667 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005668 xmlNodePtr child = NULL;
5669 xmlAttrPtr attr;
5670 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005671
Daniel Veillardc0826a72004-08-10 14:17:33 +00005672 /*
5673 * INFO: S4S completed.
5674 */
5675 /*
5676 * id = ID
5677 * {any attributes with non-schema namespace . . .}>
5678 * Content: (appinfo | documentation)*
5679 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005680 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5681 return (NULL);
5682 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005683 attr = node->properties;
5684 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005685 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005686 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005687 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005688 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005689
5690 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005691 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5692 NULL, NULL, attr);
5693 }
5694 attr = attr->next;
5695 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005696 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005697 /*
5698 * And now for the children...
5699 */
5700 child = node->children;
5701 while (child != NULL) {
5702 if (IS_SCHEMA(child, "appinfo")) {
5703 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005704 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005705 * source = anyURI
5706 * {any attributes with non-schema namespace . . .}>
5707 * Content: ({any})*
5708 */
5709 attr = child->properties;
5710 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005711 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005712 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005713 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005714 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005715
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005716 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005717 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5718 NULL, NULL, attr);
5719 }
5720 attr = attr->next;
5721 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005722 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5723 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 child = child->next;
5725 } else if (IS_SCHEMA(child, "documentation")) {
5726 /* TODO: make available the content of "documentation". */
5727 /*
5728 * source = anyURI
5729 * {any attributes with non-schema namespace . . .}>
5730 * Content: ({any})*
5731 */
5732 attr = child->properties;
5733 while (attr != NULL) {
5734 if (attr->ns == NULL) {
5735 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005736 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005737 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5738 NULL, NULL, attr);
5739 }
5740 } else {
5741 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5742 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5743 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005744
5745 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005746 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5747 NULL, NULL, attr);
5748 }
5749 }
5750 attr = attr->next;
5751 }
5752 /*
5753 * Attribute "xml:lang".
5754 */
5755 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5756 if (attr != NULL)
5757 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005758 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005759 child = child->next;
5760 } else {
5761 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005762 xmlSchemaPContentErr(ctxt,
5763 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005764 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5765 barked = 1;
5766 child = child->next;
5767 }
5768 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005769
Daniel Veillard4255d502002-04-16 15:50:10 +00005770 return (ret);
5771}
5772
5773/**
5774 * xmlSchemaParseFacet:
5775 * @ctxt: a schema validation context
5776 * @schema: the schema being built
5777 * @node: a subtree containing XML Schema informations
5778 *
5779 * parse a XML schema Facet declaration
5780 * *WARNING* this interface is highly subject to change
5781 *
5782 * Returns the new type structure or NULL in case of error
5783 */
5784static xmlSchemaFacetPtr
5785xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005786 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005787{
5788 xmlSchemaFacetPtr facet;
5789 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005790 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005791
5792 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5793 return (NULL);
5794
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005795 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005796 if (facet == NULL) {
5797 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5798 return (NULL);
5799 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005800 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005801 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005802 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005803 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5804 "Facet %s has no value\n", node->name, NULL);
5805 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005806 return (NULL);
5807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005810 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005811 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005812 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005813 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005814 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005815 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005816 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005817 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005818 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005819 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005820 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005821 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005822 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005823 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005825 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005826 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005827 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5830 } else if (IS_SCHEMA(node, "minLength")) {
5831 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5832 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005833 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5834 "Unknown facet type %s\n", node->name, NULL);
5835 xmlSchemaFreeFacet(facet);
5836 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005837 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005838 xmlSchemaPValAttrID(ctxt, NULL,
5839 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005840 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005841 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5842 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5843 const xmlChar *fixed;
5844
5845 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5846 if (fixed != NULL) {
5847 if (xmlStrEqual(fixed, BAD_CAST "true"))
5848 facet->fixed = 1;
5849 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005850 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005851 child = node->children;
5852
5853 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005854 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5855 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005856 }
5857 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005858 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5859 "Facet %s has unexpected child content\n",
5860 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005861 }
5862 return (facet);
5863}
5864
5865/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005866 * xmlSchemaParseWildcardNs:
5867 * @ctxt: a schema parser context
5868 * @wildc: the wildcard, already created
5869 * @node: a subtree containing XML Schema informations
5870 *
5871 * Parses the attribute "processContents" and "namespace"
5872 * of a xsd:anyAttribute and xsd:any.
5873 * *WARNING* this interface is highly subject to change
5874 *
5875 * Returns 0 if everything goes fine, a positive error code
5876 * if something is not valid and -1 if an internal error occurs.
5877 */
5878static int
5879xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5880 xmlSchemaPtr schema,
5881 xmlSchemaWildcardPtr wildc,
5882 xmlNodePtr node)
5883{
5884 const xmlChar *pc, *ns, *dictnsItem;
5885 int ret = 0;
5886 xmlChar *nsItem;
5887 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5888 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005889
Daniel Veillardc0826a72004-08-10 14:17:33 +00005890 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5891 if ((pc == NULL)
5892 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5893 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5894 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5895 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5896 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5897 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5898 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005899 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005900 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005901 NULL, node,
5902 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005903 NULL, NULL, NULL);
5904 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005905 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005906 }
5907 /*
5908 * Build the namespace constraints.
5909 */
5910 attr = xmlSchemaGetPropNode(node, "namespace");
5911 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005912 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005913 wildc->any = 1;
5914 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5915 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005916 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005917 return (-1);
5918 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005919 wildc->negNsSet->value = schema->targetNamespace;
5920 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005921 const xmlChar *end, *cur;
5922
5923 cur = ns;
5924 do {
5925 while (IS_BLANK_CH(*cur))
5926 cur++;
5927 end = cur;
5928 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5929 end++;
5930 if (end == cur)
5931 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005932 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005933 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5934 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005935 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005936 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005937 NULL, (xmlNodePtr) attr,
5938 NULL,
5939 "((##any | ##other) | List of (xs:anyURI | "
5940 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005941 nsItem, NULL, NULL, NULL);
5942 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5943 } else {
5944 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5945 dictnsItem = schema->targetNamespace;
5946 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5947 dictnsItem = NULL;
5948 } else {
5949 /*
5950 * Validate the item (anyURI).
5951 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005952 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005953 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5954 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5955 }
5956 /*
5957 * Avoid dublicate namespaces.
5958 */
5959 tmp = wildc->nsSet;
5960 while (tmp != NULL) {
5961 if (dictnsItem == tmp->value)
5962 break;
5963 tmp = tmp->next;
5964 }
5965 if (tmp == NULL) {
5966 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5967 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005968 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005969 return (-1);
5970 }
5971 tmp->value = dictnsItem;
5972 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005973 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005974 wildc->nsSet = tmp;
5975 else
5976 lastNs->next = tmp;
5977 lastNs = tmp;
5978 }
5979
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005980 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005981 xmlFree(nsItem);
5982 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005983 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005984 }
5985 return (ret);
5986}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005987
5988static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005989xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5990 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005991 xmlNodePtr node,
5992 int minOccurs,
5993 int maxOccurs) {
5994
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005995 if ((maxOccurs == 0) && ( minOccurs == 0))
5996 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997 if (maxOccurs != UNBOUNDED) {
5998 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005999 * TODO: Maybe we should better not create the particle,
6000 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006001 * content model.
6002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006003 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006004 * 3.9.6 Schema Component Constraint: Particle Correct
6005 *
6006 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006007 if (maxOccurs < 1) {
6008 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006009 * 2.2 {max occurs} must be greater than or equal to 1.
6010 */
6011 xmlSchemaPCustomAttrErr(ctxt,
6012 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006013 NULL, NULL,
6014 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006015 "The value must be greater than or equal to 1");
6016 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6017 } else if (minOccurs > maxOccurs) {
6018 /*
6019 * 2.1 {min occurs} must not be greater than {max occurs}.
6020 */
6021 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006022 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006023 NULL, NULL,
6024 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006025 "The value must not be greater than the value of 'maxOccurs'");
6026 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006028 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006029 return (0);
6030}
6031
Daniel Veillardc0826a72004-08-10 14:17:33 +00006032/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 * xmlSchemaParseAny:
6034 * @ctxt: a schema validation context
6035 * @schema: the schema being built
6036 * @node: a subtree containing XML Schema informations
6037 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006038 * Parsea a XML schema <any> element. A particle and wildcard
6039 * will be created (except if minOccurs==maxOccurs==0, in this case
6040 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006041 * *WARNING* this interface is highly subject to change
6042 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006043 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006044 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006045static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006046xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6047 xmlNodePtr node)
6048{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006049 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006050 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006051 xmlSchemaWildcardPtr wild;
6052 int min, max;
6053 xmlAttrPtr attr;
6054 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006055
6056 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6057 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006058 /*
6059 * Check for illegal attributes.
6060 */
6061 attr = node->properties;
6062 while (attr != NULL) {
6063 if (attr->ns == NULL) {
6064 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6065 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6066 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6067 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6068 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006069 xmlSchemaPIllegalAttrErr(ctxt,
6070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6071 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006072 }
6073 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006074 xmlSchemaPIllegalAttrErr(ctxt,
6075 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6076 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006077 }
6078 attr = attr->next;
6079 }
6080 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6081 /*
6082 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006083 */
6084 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6085 "(xs:nonNegativeInteger | unbounded)");
6086 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6087 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006088 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6089 /*
6090 * Create & parse the wildcard.
6091 */
6092 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6093 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006094 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006095 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006096 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006097 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006098 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006099 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006100 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006101 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006102 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006103 }
6104 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006105 xmlSchemaPContentErr(ctxt,
6106 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006107 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006108 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006109 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006110 /*
6111 * No component if minOccurs==maxOccurs==0.
6112 */
6113 if ((min == 0) && (max == 0)) {
6114 /* Don't free the wildcard, since it's already on the list. */
6115 return (NULL);
6116 }
6117 /*
6118 * Create the particle.
6119 */
6120 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6121 if (particle == NULL)
6122 return (NULL);
6123 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006124 wild->minOccurs = min;
6125 wild->maxOccurs = max;
6126 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006127
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006128 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006129}
6130
6131/**
6132 * xmlSchemaParseNotation:
6133 * @ctxt: a schema validation context
6134 * @schema: the schema being built
6135 * @node: a subtree containing XML Schema informations
6136 *
6137 * parse a XML schema Notation declaration
6138 *
6139 * Returns the new structure or NULL in case of error
6140 */
6141static xmlSchemaNotationPtr
6142xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006143 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006144{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006145 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006146 xmlSchemaNotationPtr ret;
6147 xmlNodePtr child = NULL;
6148
6149 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6150 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006151 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006152 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006153 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6154 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006155 return (NULL);
6156 }
6157 ret = xmlSchemaAddNotation(ctxt, schema, name);
6158 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006159 return (NULL);
6160 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006161 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006162
6163 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6164 node, BAD_CAST "id");
6165
6166 if (IS_SCHEMA(child, "annotation")) {
6167 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6168 child = child->next;
6169 }
6170
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 child = node->children;
6172 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006173 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6174 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006175 }
6176 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006177 xmlSchemaPContentErr(ctxt,
6178 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006179 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006180 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006181 }
6182
6183 return (ret);
6184}
6185
6186/**
6187 * xmlSchemaParseAnyAttribute:
6188 * @ctxt: a schema validation context
6189 * @schema: the schema being built
6190 * @node: a subtree containing XML Schema informations
6191 *
6192 * parse a XML schema AnyAttrribute declaration
6193 * *WARNING* this interface is highly subject to change
6194 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006195 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006196 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006197static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006198xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6199 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006200{
Daniel Veillard3646d642004-06-02 19:19:14 +00006201 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006203 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006204
6205 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6206 return (NULL);
6207
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006208 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6209 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006210 if (ret == NULL) {
6211 return (NULL);
6212 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006213 /*
6214 * Check for illegal attributes.
6215 */
6216 attr = node->properties;
6217 while (attr != NULL) {
6218 if (attr->ns == NULL) {
6219 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6220 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6221 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006222 xmlSchemaPIllegalAttrErr(ctxt,
6223 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6224 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006225 }
6226 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006227 xmlSchemaPIllegalAttrErr(ctxt,
6228 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6229 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006230 }
6231 attr = attr->next;
6232 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006233 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6234 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006235 /*
6236 * Parse the namespace list.
6237 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006238 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006239 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006240 /*
6241 * And now for the children...
6242 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006243 child = node->children;
6244 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006245 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6246 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006247 }
6248 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006249 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006250 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006251 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006252 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006253 }
6254
6255 return (ret);
6256}
6257
6258
6259/**
6260 * xmlSchemaParseAttribute:
6261 * @ctxt: a schema validation context
6262 * @schema: the schema being built
6263 * @node: a subtree containing XML Schema informations
6264 *
6265 * parse a XML schema Attrribute declaration
6266 * *WARNING* this interface is highly subject to change
6267 *
William M. Bracke7091952004-05-11 15:09:58 +00006268 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006269 */
6270static xmlSchemaAttributePtr
6271xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006272 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006273{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006274 const xmlChar *name, *attrValue;
6275 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006276 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006277 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006278 xmlAttrPtr attr, nameAttr;
6279 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006280
6281 /*
6282 * Note that the w3c spec assumes the schema to be validated with schema
6283 * for schemas beforehand.
6284 *
6285 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006286 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006287
6288 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6289 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006290 attr = xmlSchemaGetPropNode(node, "ref");
6291 nameAttr = xmlSchemaGetPropNode(node, "name");
6292
6293 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006294 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006295 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006296 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006297 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006298 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6299 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 "One of the attributes 'ref' or 'name' must be present");
6301 return (NULL);
6302 }
6303 if ((topLevel) || (attr == NULL)) {
6304 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006305 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6306 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006307 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006308 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006309 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006310 isRef = 1;
6311
Daniel Veillardc0826a72004-08-10 14:17:33 +00006312 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006313 char buf[50];
6314 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006315
6316 /*
6317 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006318 */
6319 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6320 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6321 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006322 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006323 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006324 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006325 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006326 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006327 if (ret == NULL) {
6328 if (repName != NULL)
6329 xmlFree(repName);
6330 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006331 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006332 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6333 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006334 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006335 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006336 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6337 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006338 /*
6339 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6340 */
6341 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006342 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6343 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006344 "ref", "name");
6345 /*
6346 * Check for illegal attributes.
6347 */
6348 attr = node->properties;
6349 while (attr != NULL) {
6350 if (attr->ns == NULL) {
6351 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6352 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006353 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006354 * 3.2.3 : 3.2
6355 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006356 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006357 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006358 xmlSchemaPIllegalAttrErr(ctxt,
6359 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006360 (xmlSchemaTypePtr) ret, attr);
6361 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6362 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6363 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006364 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6365 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006366 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006367 xmlSchemaPIllegalAttrErr(ctxt,
6368 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6369 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006370 }
6371 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006372 xmlSchemaPIllegalAttrErr(ctxt,
6373 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6374 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006375 }
6376 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006377 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006378 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006379 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006380
Daniel Veillardc0826a72004-08-10 14:17:33 +00006381 /*
6382 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006383 */
6384 if (xmlSchemaPValAttrNode(ctxt,
6385 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006386 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6387 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006388 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006389 /*
6390 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6391 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006392 /*
6393 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6394 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 */
6396 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006397 xmlSchemaPSimpleTypeErr(ctxt,
6398 XML_SCHEMAP_NO_XMLNS,
6399 NULL, (xmlNodePtr) nameAttr,
6400 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6401 "The value of type 'xs:NCName' must not match 'xmlns'",
6402 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006403 if (repName != NULL)
6404 xmlFree(repName);
6405 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006406 }
6407 /*
6408 * Evaluate the target namespace
6409 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006410 if (topLevel) {
6411 ns = schema->targetNamespace;
6412 } else {
6413 attr = xmlSchemaGetPropNode(node, "form");
6414 if (attr != NULL) {
6415 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6416 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6417 ns = schema->targetNamespace;
6418 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006419 xmlSchemaPSimpleTypeErr(ctxt,
6420 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6421 NULL, (xmlNodePtr) attr,
6422 NULL, "(qualified | unqualified)",
6423 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006424 }
6425 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006426 ns = schema->targetNamespace;
6427 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006428 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006429 if (ret == NULL) {
6430 if (repName != NULL)
6431 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006432 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006433 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006434 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006435 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006436 if (topLevel)
6437 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006438 /*
6439 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6440 * TODO: Move this to the component layer.
6441 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006442 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006443 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006444 XML_SCHEMAP_NO_XSI,
6445 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006446 "The target namespace must not match '%s'",
6447 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006448 }
6449 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006450 * Check for illegal attributes.
6451 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006452 attr = node->properties;
6453 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006454 if (attr->ns == NULL) {
6455 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6456 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6457 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6459 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006460 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006461 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6462 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006463 xmlSchemaPIllegalAttrErr(ctxt,
6464 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6465 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006466 }
6467 }
6468 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006469 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6470 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 }
6472 attr = attr->next;
6473 }
6474 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006475 node, "type", &ret->typeNs, &ret->typeName);
6476 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006477 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6478 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006479 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006480 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006481 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006482 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6483 if (ret->defValue != NULL)
6484 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006485 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006486 * Attribute "default".
6487 */
6488 attr = xmlSchemaGetPropNode(node, "default");
6489 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006490 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006491 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006492 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006493 */
6494 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6495 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6496 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6497 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006498 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6499 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006500 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006501 /*
6502 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006503 */
6504 attr = xmlSchemaGetPropNode(node, "use");
6505 if (attr != NULL) {
6506 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6507 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6508 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6509 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6510 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6511 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6512 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6513 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006514 xmlSchemaPSimpleTypeErr(ctxt,
6515 XML_SCHEMAP_INVALID_ATTR_USE,
6516 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6517 NULL, "(optional | prohibited | required)",
6518 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006519 } else
6520 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006521 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006522 * 3.2.3 : 2
6523 * If default and use are both present, use must have
6524 * the actual value optional.
6525 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006526 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6527 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006528 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006529 xmlSchemaPSimpleTypeErr(ctxt,
6530 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6531 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6532 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006533 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006534 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006535 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 /*
6538 * And now for the children...
6539 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006540 child = node->children;
6541 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006542 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6543 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006544 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006545 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 * 3.2.3 : 3.2
6550 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006551 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006552 */
6553 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6554 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6555 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006556 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6558 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006559 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006560 }
6561 } else {
6562 if (IS_SCHEMA(child, "simpleType")) {
6563 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006564 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006565 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006566 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567 */
6568 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6569 &repName, (xmlSchemaTypePtr) ret, node, child,
6570 "The attribute 'type' and the <simpleType> child "
6571 "are mutually exclusive", NULL);
6572 } else
6573 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6574 child = child->next;
6575 }
6576 if (child != NULL)
6577 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6578 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6579 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006580 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006581 /*
6582 * Cleanup.
6583 */
6584 if (repName != NULL)
6585 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006586 return (ret);
6587}
6588
6589/**
6590 * xmlSchemaParseAttributeGroup:
6591 * @ctxt: a schema validation context
6592 * @schema: the schema being built
6593 * @node: a subtree containing XML Schema informations
6594 *
6595 * parse a XML schema Attribute Group declaration
6596 * *WARNING* this interface is highly subject to change
6597 *
6598 * Returns the attribute group or NULL in case of error.
6599 */
6600static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006601xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006602 xmlSchemaPtr schema, xmlNodePtr node,
6603 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006604{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006605 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006606 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006607 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006608 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006609 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006610
6611 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6612 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006613
6614 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006615 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006616 if ((topLevel) || (attr == NULL)) {
6617 /*
6618 * Parse as an attribute group definition.
6619 * Note that those are allowed at top level only.
6620 */
6621 if (nameAttr == NULL) {
6622 xmlSchemaPMissingAttrErr(ctxt,
6623 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006624 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006625 return (NULL);
6626 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006627 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006628 * (xmlNodePtr) nameAttr);
6629 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006630 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006631 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006632 */
6633 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006634 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006635 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6636 return (NULL);
6637 }
6638 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6639 if (ret == NULL)
6640 return (NULL);
6641 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6642 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6643 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006644 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006645 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006646 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006647 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006648
6649 /*
6650 * Parse as an attribute group definition reference.
6651 */
6652 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006653 xmlSchemaPMissingAttrErr(ctxt,
6654 XML_SCHEMAP_S4S_ATTR_MISSING,
6655 NULL, node, "ref", NULL);
6656 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006657 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006658 NULL, NULL, attr, &refNs,&ref);
6659
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006660 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006661 name = (const xmlChar *) buf;
6662 if (name == NULL) {
6663 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6664 "attribute group definition reference", node);
6665 return (NULL);
6666 }
6667 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6668 if (ret == NULL)
6669 return (NULL);
6670 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6671 ret->ref = ref;
6672 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006673 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006674 xmlSchemaCheckReference(ctxt, schema, node,
6675 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006676 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006677 /*
6678 * Check for illegal attributes.
6679 */
6680 attr = node->properties;
6681 while (attr != NULL) {
6682 if (attr->ns == NULL) {
6683 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6684 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006685 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006686 {
6687 xmlSchemaPIllegalAttrErr(ctxt,
6688 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6689 NULL, NULL, attr);
6690 }
6691 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6692 xmlSchemaPIllegalAttrErr(ctxt,
6693 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6694 NULL, NULL, attr);
6695 }
6696 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006697 }
6698 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006699 /*
6700 * And now for the children...
6701 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006702 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006703 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006704 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006705 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006706 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006708 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006709 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006710 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006711 if (IS_SCHEMA(child, "anyAttribute")) {
6712 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6713 child = child->next;
6714 }
6715 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006716 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006717 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006718 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6719 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006720 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006721 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006722 ctxt->container = oldcontainer;
6723 return (ret);
6724}
6725
6726/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006727 * xmlSchemaPValAttrFormDefault:
6728 * @value: the value
6729 * @flags: the flags to be modified
6730 * @flagQualified: the specific flag for "qualified"
6731 *
6732 * Returns 0 if the value is valid, 1 otherwise.
6733 */
6734static int
6735xmlSchemaPValAttrFormDefault(const xmlChar *value,
6736 int *flags,
6737 int flagQualified)
6738{
6739 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6740 if ((*flags & flagQualified) == 0)
6741 *flags |= flagQualified;
6742 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006743 return (1);
6744
William M. Brack2f2a6632004-08-20 23:09:47 +00006745 return (0);
6746}
6747
6748/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006749 * xmlSchemaPValAttrBlockFinal:
6750 * @value: the value
6751 * @flags: the flags to be modified
6752 * @flagAll: the specific flag for "#all"
6753 * @flagExtension: the specific flag for "extension"
6754 * @flagRestriction: the specific flag for "restriction"
6755 * @flagSubstitution: the specific flag for "substitution"
6756 * @flagList: the specific flag for "list"
6757 * @flagUnion: the specific flag for "union"
6758 *
6759 * Validates the value of the attribute "final" and "block". The value
6760 * is converted into the specified flag values and returned in @flags.
6761 *
6762 * Returns 0 if the value is valid, 1 otherwise.
6763 */
6764
6765static int
6766xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006767 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006768 int flagAll,
6769 int flagExtension,
6770 int flagRestriction,
6771 int flagSubstitution,
6772 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006773 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006774{
6775 int ret = 0;
6776
6777 /*
6778 * TODO: This does not check for dublicate entries.
6779 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006780 if ((flags == NULL) || (value == NULL))
6781 return (-1);
6782 if (value[0] == 0)
6783 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006784 if (xmlStrEqual(value, BAD_CAST "#all")) {
6785 if (flagAll != -1)
6786 *flags |= flagAll;
6787 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006788 if (flagExtension != -1)
6789 *flags |= flagExtension;
6790 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006791 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006792 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006793 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006794 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006795 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006796 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006797 *flags |= flagUnion;
6798 }
6799 } else {
6800 const xmlChar *end, *cur = value;
6801 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802
Daniel Veillardc0826a72004-08-10 14:17:33 +00006803 do {
6804 while (IS_BLANK_CH(*cur))
6805 cur++;
6806 end = cur;
6807 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6808 end++;
6809 if (end == cur)
6810 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006811 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006812 if (xmlStrEqual(item, BAD_CAST "extension")) {
6813 if (flagExtension != -1) {
6814 if ((*flags & flagExtension) == 0)
6815 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006816 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006817 ret = 1;
6818 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6819 if (flagRestriction != -1) {
6820 if ((*flags & flagRestriction) == 0)
6821 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006822 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006823 ret = 1;
6824 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6825 if (flagSubstitution != -1) {
6826 if ((*flags & flagSubstitution) == 0)
6827 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006828 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006829 ret = 1;
6830 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6831 if (flagList != -1) {
6832 if ((*flags & flagList) == 0)
6833 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006834 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006835 ret = 1;
6836 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6837 if (flagUnion != -1) {
6838 if ((*flags & flagUnion) == 0)
6839 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006840 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006841 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006842 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006843 ret = 1;
6844 if (item != NULL)
6845 xmlFree(item);
6846 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006847 } while ((ret == 0) && (*cur != 0));
6848 }
6849
Daniel Veillardc0826a72004-08-10 14:17:33 +00006850 return (ret);
6851}
6852
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006853static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006854xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006855 xmlSchemaIDCPtr idc,
6856 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006857 xmlAttrPtr attr,
6858 int isField)
6859{
6860 xmlNodePtr node;
6861
6862 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006863 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006864 * Schema Component Constraint: Selector Value OK
6865 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006866 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006867 * in [XPath].
6868 */
6869 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006870 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006871 XML_SCHEMAP_INTERNAL,
6872 "Internal error: xmlSchemaCheckCSelectorXPath, "
6873 "the selector is not specified.\n", NULL, NULL);
6874 return (-1);
6875 }
6876 if (attr == NULL)
6877 node = idc->node;
6878 else
6879 node = (xmlNodePtr) attr;
6880 if (selector->xpath == NULL) {
6881 xmlSchemaPCustomErr(ctxt,
6882 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006883 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6884 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006885 "The XPath expression of the selector is not valid", NULL);
6886 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6887 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006888 const xmlChar **nsArray = NULL;
6889 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006890 /*
6891 * Compile the XPath expression.
6892 */
6893 /*
6894 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006895 * TODO: Call xmlPatterncompile with different options for selector/
6896 * field.
6897 */
6898 nsList = xmlGetNsList(attr->doc, attr->parent);
6899 /*
6900 * Build an array of prefixes and namespaces.
6901 */
6902 if (nsList != NULL) {
6903 int i, count = 0;
6904 xmlNsPtr ns;
6905
6906 for (i = 0; nsList[i] != NULL; i++)
6907 count++;
6908
6909 nsArray = (const xmlChar **) xmlMalloc(
6910 (count * 2 + 1) * sizeof(const xmlChar *));
6911 if (nsArray == NULL) {
6912 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6913 NULL);
6914 return (-1);
6915 }
6916 for (i = 0; i < count; i++) {
6917 ns = nsList[i];
6918 nsArray[2 * i] = nsList[i]->href;
6919 nsArray[2 * i + 1] = nsList[i]->prefix;
6920 }
6921 nsArray[count * 2] = NULL;
6922 xmlFree(nsList);
6923 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006924 /*
6925 * TODO: Differentiate between "selector" and "field".
6926 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006927 if (isField)
6928 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006929 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006930 else
6931 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006932 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006933 if (nsArray != NULL)
6934 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006935
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006936 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006937 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006938 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006939 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6940 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006941 "The XPath expression '%s' could not be "
6942 "compiled", selector->xpath);
6943 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006944 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006945 }
6946 return (0);
6947}
6948
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006949#define ADD_ANNOTATION(annot) \
6950 xmlSchemaAnnotPtr cur = item->annot; \
6951 if (item->annot == NULL) { \
6952 item->annot = annot; \
6953 return (annot); \
6954 } \
6955 cur = item->annot; \
6956 if (cur->next != NULL) { \
6957 cur = cur->next; \
6958 } \
6959 cur->next = annot;
6960
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006961/**
6962 * xmlSchemaAssignAnnotation:
6963 * @item: the schema component
6964 * @annot: the annotation
6965 *
6966 * Adds the annotation to the given schema component.
6967 *
6968 * Returns the given annotaion.
6969 */
6970static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006971xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6972 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006973{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006974 if ((annItem == NULL) || (annot == NULL))
6975 return (NULL);
6976 switch (annItem->type) {
6977 case XML_SCHEMA_TYPE_ELEMENT: {
6978 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6979 ADD_ANNOTATION(annot)
6980 }
6981 break;
6982 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6983 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6984 ADD_ANNOTATION(annot)
6985 }
6986 break;
6987 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6988 case XML_SCHEMA_TYPE_ANY: {
6989 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6990 ADD_ANNOTATION(annot)
6991 }
6992 break;
6993 case XML_SCHEMA_TYPE_PARTICLE:
6994 case XML_SCHEMA_TYPE_IDC_KEY:
6995 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006996 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006997 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6998 ADD_ANNOTATION(annot)
6999 }
7000 break;
7001 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7002 xmlSchemaAttributeGroupPtr item =
7003 (xmlSchemaAttributeGroupPtr) annItem;
7004 ADD_ANNOTATION(annot)
7005 }
7006 break;
7007 case XML_SCHEMA_TYPE_NOTATION: {
7008 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7009 ADD_ANNOTATION(annot)
7010 }
7011 break;
7012 case XML_SCHEMA_FACET_MININCLUSIVE:
7013 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7014 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7015 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7016 case XML_SCHEMA_FACET_TOTALDIGITS:
7017 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7018 case XML_SCHEMA_FACET_PATTERN:
7019 case XML_SCHEMA_FACET_ENUMERATION:
7020 case XML_SCHEMA_FACET_WHITESPACE:
7021 case XML_SCHEMA_FACET_LENGTH:
7022 case XML_SCHEMA_FACET_MAXLENGTH:
7023 case XML_SCHEMA_FACET_MINLENGTH: {
7024 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7025 ADD_ANNOTATION(annot)
7026 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007027 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007028 case XML_SCHEMA_TYPE_SIMPLE:
7029 case XML_SCHEMA_TYPE_COMPLEX: {
7030 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7031 ADD_ANNOTATION(annot)
7032 }
7033 break;
7034 case XML_SCHEMA_TYPE_GROUP: {
7035 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7036 ADD_ANNOTATION(annot)
7037 }
7038 break;
7039 case XML_SCHEMA_TYPE_SEQUENCE:
7040 case XML_SCHEMA_TYPE_CHOICE:
7041 case XML_SCHEMA_TYPE_ALL: {
7042 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7043 ADD_ANNOTATION(annot)
7044 }
7045 break;
7046 default:
7047 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007048 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007049 NULL, NULL, NULL,
7050 "Internal error: xmlSchemaAddAnnotation, "
7051 "The item is not a annotated schema component", NULL);
7052 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007053 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007054 return (annot);
7055}
7056
7057/**
7058 * xmlSchemaParseIDCSelectorAndField:
7059 * @ctxt: a schema validation context
7060 * @schema: the schema being built
7061 * @node: a subtree containing XML Schema informations
7062 *
7063 * Parses a XML Schema identity-contraint definition's
7064 * <selector> and <field> elements.
7065 *
7066 * Returns the parsed identity-constraint definition.
7067 */
7068static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007069xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007070 xmlSchemaPtr schema,
7071 xmlSchemaIDCPtr idc,
7072 xmlNodePtr node,
7073 int isField)
7074{
7075 xmlSchemaIDCSelectPtr item;
7076 xmlNodePtr child = NULL;
7077 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007078
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007079 /*
7080 * Check for illegal attributes.
7081 */
7082 attr = node->properties;
7083 while (attr != NULL) {
7084 if (attr->ns == NULL) {
7085 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7086 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007087 xmlSchemaPIllegalAttrErr(ctxt,
7088 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7089 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007090 }
7091 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007092 xmlSchemaPIllegalAttrErr(ctxt,
7093 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7094 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007095 }
7096 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007097 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007098 /*
7099 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007100 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007101 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7102 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007103 xmlSchemaPErrMemory(ctxt,
7104 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007105 NULL);
7106 return (NULL);
7107 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007108 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007109 /*
7110 * Attribute "xpath" (mandatory).
7111 */
7112 attr = xmlSchemaGetPropNode(node, "xpath");
7113 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007114 xmlSchemaPMissingAttrErr(ctxt,
7115 XML_SCHEMAP_S4S_ATTR_MISSING,
7116 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007117 "name", NULL);
7118 } else {
7119 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7120 /*
7121 * URGENT TODO: "field"s have an other syntax than "selector"s.
7122 */
7123
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007124 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7125 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007126 xmlSchemaPErr(ctxt,
7127 (xmlNodePtr) attr,
7128 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007129 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007130 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007131 NULL, NULL);
7132 }
7133
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007134 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007135 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007136 /*
7137 * And now for the children...
7138 */
7139 child = node->children;
7140 if (IS_SCHEMA(child, "annotation")) {
7141 /*
7142 * Add the annotation to the parent IDC.
7143 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007144 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007145 xmlSchemaParseAnnotation(ctxt, schema, child));
7146 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007147 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007148 if (child != NULL) {
7149 xmlSchemaPContentErr(ctxt,
7150 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007151 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007152 NULL, "(annotation?)");
7153 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007154
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007155 return (item);
7156}
7157
7158/**
7159 * xmlSchemaParseIDC:
7160 * @ctxt: a schema validation context
7161 * @schema: the schema being built
7162 * @node: a subtree containing XML Schema informations
7163 *
7164 * Parses a XML Schema identity-contraint definition.
7165 *
7166 * Returns the parsed identity-constraint definition.
7167 */
7168static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007169xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007170 xmlSchemaPtr schema,
7171 xmlNodePtr node,
7172 xmlSchemaTypeType idcCategory,
7173 const xmlChar *targetNamespace)
7174{
7175 xmlSchemaIDCPtr item = NULL;
7176 xmlNodePtr child = NULL;
7177 xmlAttrPtr attr;
7178 const xmlChar *name = NULL;
7179 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7180 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007181
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007182 /*
7183 * Check for illegal attributes.
7184 */
7185 attr = node->properties;
7186 while (attr != NULL) {
7187 if (attr->ns == NULL) {
7188 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7189 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7190 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7191 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007192 xmlSchemaPIllegalAttrErr(ctxt,
7193 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7194 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007195 }
7196 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007197 xmlSchemaPIllegalAttrErr(ctxt,
7198 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7199 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007200 }
7201 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007202 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007203 /*
7204 * Attribute "name" (mandatory).
7205 */
7206 attr = xmlSchemaGetPropNode(node, "name");
7207 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007208 xmlSchemaPMissingAttrErr(ctxt,
7209 XML_SCHEMAP_S4S_ATTR_MISSING,
7210 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007211 "name", NULL);
7212 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007213 } else if (xmlSchemaPValAttrNode(ctxt,
7214 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007215 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7216 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007217 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007218 /*
7219 * Create the component.
7220 */
7221 if (schema->idcDef == NULL)
7222 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007223 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007224 return (NULL);
7225
7226 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7227 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007228 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007229 "allocating an identity-constraint definition", NULL);
7230 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007231 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007232 /*
7233 * Add the IDC to the list of IDCs on the schema component.
7234 */
7235 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007236 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007237 xmlSchemaPCustomErrExt(ctxt,
7238 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007239 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007240 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007241 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007242 name, targetNamespace, NULL);
7243 xmlFree(item);
7244 return (NULL);
7245 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007246 memset(item, 0, sizeof(xmlSchemaIDC));
7247 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007248 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007249 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007250 if (ctxt->assemble != NULL)
7251 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007252 /*
7253 * The target namespace of the parent element declaration.
7254 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007255 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007256 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7257 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007258 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7259 /*
7260 * Attribute "refer" (mandatory).
7261 */
7262 attr = xmlSchemaGetPropNode(node, "refer");
7263 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007264 xmlSchemaPMissingAttrErr(ctxt,
7265 XML_SCHEMAP_S4S_ATTR_MISSING,
7266 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007267 "refer", NULL);
7268 } else {
7269 /*
7270 * Create a reference item.
7271 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007272 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007273 NULL, NULL);
7274 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007275 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007276 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007277 NULL, NULL, attr,
7278 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007279 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007280 xmlSchemaCheckReference(ctxt, schema, node,
7281 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007282 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007283 }
7284 }
7285 /*
7286 * And now for the children...
7287 */
7288 child = node->children;
7289 if (IS_SCHEMA(child, "annotation")) {
7290 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7291 child = child->next;
7292 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007293 if (child == NULL) {
7294 xmlSchemaPContentErr(ctxt,
7295 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007296 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007297 "A child element is missing",
7298 "(annotation?, (selector, field+))");
7299 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007300 /*
7301 * Child element <selector>.
7302 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007303 if (IS_SCHEMA(child, "selector")) {
7304 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007305 item, child, 0);
7306 child = child->next;
7307 /*
7308 * Child elements <field>.
7309 */
7310 if (IS_SCHEMA(child, "field")) {
7311 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007312 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007313 item, child, 1);
7314 if (field != NULL) {
7315 field->index = item->nbFields;
7316 item->nbFields++;
7317 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007318 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007319 else
7320 item->fields = field;
7321 lastField = field;
7322 }
7323 child = child->next;
7324 } while (IS_SCHEMA(child, "field"));
7325 } else {
7326 xmlSchemaPContentErr(ctxt,
7327 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007328 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007329 NULL, "(annotation?, (selector, field+))");
7330 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007331 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007332 if (child != NULL) {
7333 xmlSchemaPContentErr(ctxt,
7334 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007335 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007336 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007337 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007338
7339 return (item);
7340}
7341
Daniel Veillardc0826a72004-08-10 14:17:33 +00007342/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007343 * xmlSchemaParseElement:
7344 * @ctxt: a schema validation context
7345 * @schema: the schema being built
7346 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007347 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007348 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007349 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007350 * *WARNING* this interface is highly subject to change
7351 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007352 * Returns the element declaration or a particle; NULL in case
7353 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007354 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007355static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007356xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007357 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007358{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007359 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007360 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007361 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007362 xmlNodePtr child = NULL;
7363 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007364 int min, max, isRef = 0;
7365 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007366
7367 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7368 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007369
Daniel Veillard4255d502002-04-16 15:50:10 +00007370 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007371 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007372 /*
7373 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007374 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007375 * robust.
7376 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007377 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007378 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007379 if ((topLevel) || (attr == NULL)) {
7380 if (nameAttr == NULL) {
7381 xmlSchemaPMissingAttrErr(ctxt,
7382 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007383 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007384 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007385 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007386 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007387 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007388
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007389 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007390 child = node->children;
7391 if (IS_SCHEMA(child, "annotation")) {
7392 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7393 child = child->next;
7394 }
7395 /*
7396 * Skip particle part if a global declaration.
7397 */
7398 if (topLevel)
7399 goto declaration_part;
7400 /*
7401 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007402 */
7403 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7404 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7405 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007406 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7407 if (particle == NULL)
7408 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007409
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007410 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7411
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007412 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007413 const xmlChar *refNs = NULL, *ref = NULL;
7414 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007415 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007416 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007417 */
7418 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007419 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007420 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007421 /*
7422 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007423 */
7424 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007425 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007426 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007427 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007428 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007429 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007430 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007431 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007432 attr = node->properties;
7433 while (attr != NULL) {
7434 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007435 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7436 xmlStrEqual(attr->name, BAD_CAST "name") ||
7437 xmlStrEqual(attr->name, BAD_CAST "id") ||
7438 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7439 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7440 {
7441 attr = attr->next;
7442 continue;
7443 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007444 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007445 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007446 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007447 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007448 "Only the attributes 'minOccurs', 'maxOccurs' and "
7449 "'id' are allowed in addition to 'ref'");
7450 break;
7451 }
7452 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7453 xmlSchemaPIllegalAttrErr(ctxt,
7454 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007455 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007456 }
7457 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007458 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007459 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007460 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007461 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007462 if (child != NULL) {
7463 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 NULL, NULL, node, child, NULL, "(annotation?)");
7465 }
7466 if ((min == 0) && (max == 0))
7467 goto return_null;
7468 /*
7469 * Create the reference item.
7470 */
7471 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7472 ref, refNs);
7473 if (refer == NULL)
7474 goto return_null;
7475 particle->children = (xmlSchemaTreeItemPtr) refer;
7476 particle->annot = annot;
7477 /*
7478 * Add to assembled items; the reference need to be resolved.
7479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007480 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007481 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7482
7483 return ((xmlSchemaBasicItemPtr) particle);
7484 }
7485 /*
7486 * The declaration part ===============================================
7487 */
7488declaration_part:
7489 {
7490 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7491 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7492
7493 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007494 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007495 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007496 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007497 * Evaluate the target namespace.
7498 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007499 if (topLevel) {
7500 ns = schema->targetNamespace;
7501 } else {
7502 attr = xmlSchemaGetPropNode(node, "form");
7503 if (attr != NULL) {
7504 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7505 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007506 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007507 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007508 xmlSchemaPSimpleTypeErr(ctxt,
7509 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7510 NULL, (xmlNodePtr) attr,
7511 NULL, "(qualified | unqualified)",
7512 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007513 }
7514 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007515 ns = schema->targetNamespace;
7516 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007517 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007518 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007519 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007520 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007521 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7522 decl->node = node;
7523 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007524 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007525 * Check for illegal attributes.
7526 */
William M. Bracke7091952004-05-11 15:09:58 +00007527 attr = node->properties;
7528 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007529 if (attr->ns == NULL) {
7530 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7531 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007532 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007533 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007534 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007536 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7537 {
7538 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007539 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007540 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007541 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007542 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007543 xmlSchemaPIllegalAttrErr(ctxt,
7544 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7545 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007546 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007547 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7548 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007549 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7550
7551 xmlSchemaPIllegalAttrErr(ctxt,
7552 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007553 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007554 }
7555 }
7556 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007557
Daniel Veillardc0826a72004-08-10 14:17:33 +00007558 xmlSchemaPIllegalAttrErr(ctxt,
7559 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007560 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007561 }
7562 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007563 }
William M. Bracke7091952004-05-11 15:09:58 +00007564 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007565 * Extract/validate attributes.
7566 */
7567 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007568 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007569 * Process top attributes of global element declarations here.
7570 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007571 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7572 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007573 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7574 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7575 &(decl->substGroupNs), &(decl->substGroup));
7576 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007577 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007578 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007579 /*
7580 * Attribute "final".
7581 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007582 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007583 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007584 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7585 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7586 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7587 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007588 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007589 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7590 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007591 -1,
7592 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7593 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007594 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007595 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007596 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7597 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007598 attrValue, NULL, NULL, NULL);
7599 }
7600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007601 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007602 /*
7603 * Attribute "block".
7604 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007605 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007606 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007607 /*
7608 * Apply default "block" values.
7609 */
7610 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7611 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7612 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7613 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7614 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7615 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007616 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007617 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7618 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007619 -1,
7620 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007621 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007622 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7623 xmlSchemaPSimpleTypeErr(ctxt,
7624 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007625 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007626 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007627 "restriction | substitution))", attrValue,
7628 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007629 }
7630 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007631 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007632 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007633 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007634
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007635 attr = xmlSchemaGetPropNode(node, "type");
7636 if (attr != NULL) {
7637 xmlSchemaPValAttrNodeQName(ctxt, schema,
7638 NULL, (xmlSchemaTypePtr) decl, attr,
7639 &(decl->namedTypeNs), &(decl->namedType));
7640 xmlSchemaCheckReference(ctxt, schema, node,
7641 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7642 }
7643 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7644 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007645 if (attr != NULL) {
7646 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007647 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007648 /*
7649 * 3.3.3 : 1
7650 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007651 */
7652 xmlSchemaPMutualExclAttrErr(ctxt,
7653 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007654 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007655 "default", "fixed");
7656 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007657 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7658 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007659 }
William M. Bracke7091952004-05-11 15:09:58 +00007660 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007661 /*
7662 * And now for the children...
7663 */
7664 oldcontainer = ctxt->container;
7665 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007666 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007667 /*
7668 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007669 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007670 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007671 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007672 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007673 xmlSchemaPContentErr(ctxt,
7674 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007675 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007676 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007677 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007678 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007679 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007680 child = child->next;
7681 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007682 /*
7683 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007684 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007685 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007686 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007687 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 xmlSchemaPContentErr(ctxt,
7689 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007690 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007691 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007692 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007693 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007694 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007695 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007696 }
William M. Bracke7091952004-05-11 15:09:58 +00007697 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007698 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007699 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007700 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007701 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007702 } else if (IS_SCHEMA(child, "key")) {
7703 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007704 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007705 } else if (IS_SCHEMA(child, "keyref")) {
7706 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007707 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007708 }
7709 if (lastIDC != NULL)
7710 lastIDC->next = curIDC;
7711 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007712 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007713 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007714 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007715 }
7716 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007717 xmlSchemaPContentErr(ctxt,
7718 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007719 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007720 NULL, "(annotation?, ((simpleType | complexType)?, "
7721 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007722 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007723 ctxt->container = oldcontainer;
7724 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007725 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007726 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007727 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007728 * different layer.
7729 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007730 FREE_AND_NULL(des)
7731 if (topLevel)
7732 return ((xmlSchemaBasicItemPtr) decl);
7733 else {
7734 particle->children = (xmlSchemaTreeItemPtr) decl;
7735 return ((xmlSchemaBasicItemPtr) particle);
7736 }
7737
7738return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007739 FREE_AND_NULL(des);
7740 if (annot != NULL) {
7741 if (particle != NULL)
7742 particle->annot = NULL;
7743 if (decl != NULL)
7744 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007745 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007746 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007747 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007748}
7749
7750/**
7751 * xmlSchemaParseUnion:
7752 * @ctxt: a schema validation context
7753 * @schema: the schema being built
7754 * @node: a subtree containing XML Schema informations
7755 *
7756 * parse a XML schema Union definition
7757 * *WARNING* this interface is highly subject to change
7758 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007759 * Returns -1 in case of internal error, 0 in case of success and a positive
7760 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007761 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007762static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007763xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007764 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007766 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007767 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007768 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007769 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007770
7771 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007772 return (-1);
7773 /* Not a component, don't create it. */
7774 type = ctxt->ctxtType;
7775 /*
7776 * Mark the simple type as being of variety "union".
7777 */
7778 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007779 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007780 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7781 * then the ·simple ur-type definition·."
7782 */
7783 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007784 /*
7785 * Check for illegal attributes.
7786 */
7787 attr = node->properties;
7788 while (attr != NULL) {
7789 if (attr->ns == NULL) {
7790 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7791 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007792 xmlSchemaPIllegalAttrErr(ctxt,
7793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7794 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007795 }
7796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007797 xmlSchemaPIllegalAttrErr(ctxt,
7798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7799 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007800 }
7801 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007802 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007803 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007804 /*
7805 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007806 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007807 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007808 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007809 if (attr != NULL) {
7810 const xmlChar *end;
7811 xmlChar *tmp;
7812 const xmlChar *localName, *nsName;
7813 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7814 xmlSchemaQNameRefPtr ref;
7815
7816 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007817 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007818 do {
7819 while (IS_BLANK_CH(*cur))
7820 cur++;
7821 end = cur;
7822 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7823 end++;
7824 if (end == cur)
7825 break;
7826 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007827 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7828 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007829 /*
7830 * Create the member type link.
7831 */
7832 link = (xmlSchemaTypeLinkPtr)
7833 xmlMalloc(sizeof(xmlSchemaTypeLink));
7834 if (link == NULL) {
7835 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7836 "allocating a type link", NULL);
7837 return (-1);
7838 }
7839 link->type = NULL;
7840 link->next = NULL;
7841 if (lastLink == NULL)
7842 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007843 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007844 lastLink->next = link;
7845 lastLink = link;
7846 /*
7847 * Create a reference item.
7848 */
7849 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7850 localName, nsName);
7851 if (ref == NULL) {
7852 FREE_AND_NULL(tmp)
7853 return (-1);
7854 }
7855 /*
7856 * Assign the reference to the link, it will be resolved
7857 * later during fixup of the union simple type.
7858 */
7859 link->type = (xmlSchemaTypePtr) ref;
7860 }
7861 FREE_AND_NULL(tmp)
7862 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007863 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007864
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007865 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007866 /*
7867 * And now for the children...
7868 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007869 child = node->children;
7870 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007871 /*
7872 * Add the annotation to the simple type ancestor.
7873 */
7874 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7875 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007876 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007877 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007878 if (IS_SCHEMA(child, "simpleType")) {
7879 xmlSchemaTypePtr subtype, last = NULL;
7880
7881 /*
7882 * Anchor the member types in the "subtypes" field of the
7883 * simple type.
7884 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007885 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007886 subtype = (xmlSchemaTypePtr)
7887 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7888 if (subtype != NULL) {
7889 if (last == NULL) {
7890 type->subtypes = subtype;
7891 last = subtype;
7892 } else {
7893 last->next = subtype;
7894 last = subtype;
7895 }
7896 last->next = NULL;
7897 }
7898 child = child->next;
7899 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007900 }
7901 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007902 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007903 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007904 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007905 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007906 if ((attr == NULL) && (type->subtypes == NULL)) {
7907 /*
7908 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007909 * Either the memberTypes [attribute] of the <union> element must
7910 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007911 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007912 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007913 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7914 NULL, NULL, node,
7915 "Either the attribute 'memberTypes' or "
7916 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007917 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007918 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007919}
7920
7921/**
7922 * xmlSchemaParseList:
7923 * @ctxt: a schema validation context
7924 * @schema: the schema being built
7925 * @node: a subtree containing XML Schema informations
7926 *
7927 * parse a XML schema List definition
7928 * *WARNING* this interface is highly subject to change
7929 *
William M. Bracke7091952004-05-11 15:09:58 +00007930 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007931 * 1 in case of success.
7932 */
7933static xmlSchemaTypePtr
7934xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007935 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007936{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007937 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007938 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007939 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007940
7941 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7942 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007943 /* Not a component, don't create it. */
7944 type = ctxt->ctxtType;
7945 /*
7946 * Mark the type as being of variety "list".
7947 */
7948 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007949 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007950 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7951 * then the ·simple ur-type definition·."
7952 */
7953 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007954 /*
7955 * Check for illegal attributes.
7956 */
7957 attr = node->properties;
7958 while (attr != NULL) {
7959 if (attr->ns == NULL) {
7960 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7961 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007962 xmlSchemaPIllegalAttrErr(ctxt,
7963 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7964 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007965 }
7966 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007967 xmlSchemaPIllegalAttrErr(ctxt,
7968 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7969 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007970 }
7971 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007972 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007973
7974 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7975
William M. Brack2f2a6632004-08-20 23:09:47 +00007976 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007977 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7978 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007979 */
7980 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007981 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007982 /*
7983 * And now for the children...
7984 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007985 child = node->children;
7986 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7988 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007989 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007990 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007991 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007992 /*
7993 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007994 * Either the itemType [attribute] or the <simpleType> [child] of
7995 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007996 */
7997 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007998 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00007999 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008000 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008001 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008002 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008003 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008004 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008005 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008006 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008007 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008008 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008009 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008010 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008011 "Either the attribute 'itemType' or the <simpleType> child "
8012 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008013 }
8014 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008015 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008016 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008017 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008018 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008019 if ((type->ref == NULL) &&
8020 (type->subtypes == NULL) &&
8021 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008022 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008023 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008024 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008025 "Either the attribute 'itemType' or the <simpleType> child "
8026 "must be present", NULL);
8027 }
8028 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008029}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008030
Daniel Veillard4255d502002-04-16 15:50:10 +00008031/**
8032 * xmlSchemaParseSimpleType:
8033 * @ctxt: a schema validation context
8034 * @schema: the schema being built
8035 * @node: a subtree containing XML Schema informations
8036 *
8037 * parse a XML schema Simple Type definition
8038 * *WARNING* this interface is highly subject to change
8039 *
William M. Bracke7091952004-05-11 15:09:58 +00008040 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008041 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008042 */
8043static xmlSchemaTypePtr
8044xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008045 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008046{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008047 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008048 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008049 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008050 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008051
8052 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8053 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008054
Daniel Veillardc0826a72004-08-10 14:17:33 +00008055 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008056 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008057 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008058 xmlSchemaPMissingAttrErr(ctxt,
8059 XML_SCHEMAP_S4S_ATTR_MISSING,
8060 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008061 "name", NULL);
8062 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008063 } else {
8064 if (xmlSchemaPValAttrNode(ctxt,
8065 NULL, NULL, attr,
8066 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8067 return (NULL);
8068 /*
8069 * Skip built-in types.
8070 */
8071 if (ctxt->isS4S) {
8072 xmlSchemaTypePtr biType;
8073
8074 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8075 if (biType != NULL)
8076 return (biType);
8077 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008078 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008079 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008080
Daniel Veillardc0826a72004-08-10 14:17:33 +00008081 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008082 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008083
Daniel Veillard01fa6152004-06-29 17:04:39 +00008084 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008085 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008086 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008087 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008088 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008089 if (type == NULL)
8090 return (NULL);
8091 type->node = node;
8092 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008093 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008094 /*
8095 * Check for illegal attributes.
8096 */
8097 attr = node->properties;
8098 while (attr != NULL) {
8099 if (attr->ns == NULL) {
8100 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008101 xmlSchemaPIllegalAttrErr(ctxt,
8102 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8103 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008104 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008105 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008106 xmlSchemaPIllegalAttrErr(ctxt,
8107 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8108 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008109 }
8110 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008111 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008112 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008113 /*
8114 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008115 *
8116 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008117 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008118 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008119 if (type == NULL)
8120 return (NULL);
8121 type->node = node;
8122 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008123 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008124 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8125 /*
8126 * Check for illegal attributes.
8127 */
8128 attr = node->properties;
8129 while (attr != NULL) {
8130 if (attr->ns == NULL) {
8131 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8132 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008133 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008134 xmlSchemaPIllegalAttrErr(ctxt,
8135 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8136 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008137 }
8138 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008139 xmlSchemaPIllegalAttrErr(ctxt,
8140 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8141 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008142 }
8143 attr = attr->next;
8144 }
8145 /*
8146 * Attribute "final".
8147 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008148 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008149 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008150 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8151 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8152 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8153 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8154 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8155 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008156 } else {
8157 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008158 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8159 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008160 XML_SCHEMAS_TYPE_FINAL_LIST,
8161 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8162
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008163 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008164 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008165 type, (xmlNodePtr) attr,
8166 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008167 attrValue, NULL, NULL, NULL);
8168 }
8169 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008170 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008171 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008172 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008173 /*
8174 * And now for the children...
8175 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008176 oldCtxtType = ctxt->ctxtType;
8177 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008178 ctxt->ctxtType = type;
8179 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008180 child = node->children;
8181 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008182 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8183 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008184 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008185 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008186 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8187 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008188 "(annotation?, (restriction | list | union))");
8189 } else if (IS_SCHEMA(child, "restriction")) {
8190 xmlSchemaParseRestriction(ctxt, schema, child,
8191 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008192 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008193 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008194 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008195 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008196 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008197 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008198 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008199 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008200 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008201 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8202 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008203 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008204 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008205 ctxt->parentItem = oldParentItem;
8206 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008207
Daniel Veillard4255d502002-04-16 15:50:10 +00008208 return (type);
8209}
8210
Daniel Veillard4255d502002-04-16 15:50:10 +00008211/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008212 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008213 * @ctxt: a schema validation context
8214 * @schema: the schema being built
8215 * @node: a subtree containing XML Schema informations
8216 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008217 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008218 * *WARNING* this interface is highly subject to change
8219 *
William M. Bracke7091952004-05-11 15:09:58 +00008220 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008221 * 1 in case of success.
8222 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008223static xmlSchemaTreeItemPtr
8224xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8225 xmlSchemaPtr schema,
8226 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008227{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008228 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008229 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008230 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008231 const xmlChar *ref = NULL, *refNs = NULL;
8232 int min, max;
8233
8234 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008235 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008236
8237 attr = xmlSchemaGetPropNode(node, "ref");
8238 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008239 xmlSchemaPMissingAttrErr(ctxt,
8240 XML_SCHEMAP_S4S_ATTR_MISSING,
8241 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008242 "ref", NULL);
8243 return (NULL);
8244 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008245 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008246 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008247 }
8248 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008249 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008250 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008251 /*
8252 * Check for illegal attributes.
8253 */
8254 attr = node->properties;
8255 while (attr != NULL) {
8256 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008257 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008258 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8259 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8260 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008261 xmlSchemaPIllegalAttrErr(ctxt,
8262 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8263 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008264 }
8265 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008266 xmlSchemaPIllegalAttrErr(ctxt,
8267 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8268 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008269 }
8270 attr = attr->next;
8271 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008272 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008273 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8274 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008275 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008276 /*
8277 * Create a reference item as the term; it will be substituted for
8278 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008279 */
8280 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008281 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8282 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8283 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8284 /*
8285 * And now for the children...
8286 */
8287 child = node->children;
8288 /* TODO: Is annotation even allowed for a model group reference? */
8289 if (IS_SCHEMA(child, "annotation")) {
8290 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008291 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008292 */
8293 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8294 child = child->next;
8295 }
8296 if (child != NULL) {
8297 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008298 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008299 NULL, NULL, node, child, NULL,
8300 "(annotation?)");
8301 }
8302 /*
8303 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8304 */
8305 if ((min == 0) && (max == 0))
8306 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008307 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008308 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8309 return ((xmlSchemaTreeItemPtr) item);
8310}
8311
8312/**
8313 * xmlSchemaParseModelGroupDefinition:
8314 * @ctxt: a schema validation context
8315 * @schema: the schema being built
8316 * @node: a subtree containing XML Schema informations
8317 *
8318 * Parses a XML schema model group definition.
8319 * *WARNING* this interface is highly subject to change
8320 *
8321 * Returns -1 in case of error, 0 if the declaration is improper and
8322 * 1 in case of success.
8323 */
8324static xmlSchemaModelGroupDefPtr
8325xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8326 xmlSchemaPtr schema,
8327 xmlNodePtr node)
8328{
8329 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008330 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008331 xmlAttrPtr attr;
8332 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008333
8334 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008335 return (NULL);
8336
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008337 attr = xmlSchemaGetPropNode(node, "name");
8338 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008339 xmlSchemaPMissingAttrErr(ctxt,
8340 XML_SCHEMAP_S4S_ATTR_MISSING,
8341 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008342 "name", NULL);
8343 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008344 } else if (xmlSchemaPValAttrNode(ctxt,
8345 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008346 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8347 return (NULL);
8348 }
8349 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8350 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008351 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008352 /*
8353 * Check for illegal attributes.
8354 */
8355 attr = node->properties;
8356 while (attr != NULL) {
8357 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008358 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008359 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008360 xmlSchemaPIllegalAttrErr(ctxt,
8361 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8362 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008363 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008364 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008365 xmlSchemaPIllegalAttrErr(ctxt,
8366 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8367 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008368 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008369 attr = attr->next;
8370 }
8371 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8372 /*
8373 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008374 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008375 child = node->children;
8376 if (IS_SCHEMA(child, "annotation")) {
8377 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8378 child = child->next;
8379 }
8380 if (IS_SCHEMA(child, "all")) {
8381 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8382 XML_SCHEMA_TYPE_ALL, 0);
8383 child = child->next;
8384 } else if (IS_SCHEMA(child, "choice")) {
8385 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8386 XML_SCHEMA_TYPE_CHOICE, 0);
8387 child = child->next;
8388 } else if (IS_SCHEMA(child, "sequence")) {
8389 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8390 XML_SCHEMA_TYPE_SEQUENCE, 0);
8391 child = child->next;
8392 }
8393 if (child != NULL) {
8394 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008395 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8396 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008397 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008398 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008399
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008400 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008401}
8402
8403/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008404 * xmlSchemaCleanupDoc:
8405 * @ctxt: a schema validation context
8406 * @node: the root of the document.
8407 *
8408 * removes unwanted nodes in a schemas document tree
8409 */
8410static void
8411xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8412{
8413 xmlNodePtr delete, cur;
8414
8415 if ((ctxt == NULL) || (root == NULL)) return;
8416
8417 /*
8418 * Remove all the blank text nodes
8419 */
8420 delete = NULL;
8421 cur = root;
8422 while (cur != NULL) {
8423 if (delete != NULL) {
8424 xmlUnlinkNode(delete);
8425 xmlFreeNode(delete);
8426 delete = NULL;
8427 }
8428 if (cur->type == XML_TEXT_NODE) {
8429 if (IS_BLANK_NODE(cur)) {
8430 if (xmlNodeGetSpacePreserve(cur) != 1) {
8431 delete = cur;
8432 }
8433 }
8434 } else if ((cur->type != XML_ELEMENT_NODE) &&
8435 (cur->type != XML_CDATA_SECTION_NODE)) {
8436 delete = cur;
8437 goto skip_children;
8438 }
8439
8440 /*
8441 * Skip to next node
8442 */
8443 if (cur->children != NULL) {
8444 if ((cur->children->type != XML_ENTITY_DECL) &&
8445 (cur->children->type != XML_ENTITY_REF_NODE) &&
8446 (cur->children->type != XML_ENTITY_NODE)) {
8447 cur = cur->children;
8448 continue;
8449 }
8450 }
8451 skip_children:
8452 if (cur->next != NULL) {
8453 cur = cur->next;
8454 continue;
8455 }
8456
8457 do {
8458 cur = cur->parent;
8459 if (cur == NULL)
8460 break;
8461 if (cur == root) {
8462 cur = NULL;
8463 break;
8464 }
8465 if (cur->next != NULL) {
8466 cur = cur->next;
8467 break;
8468 }
8469 } while (cur != NULL);
8470 }
8471 if (delete != NULL) {
8472 xmlUnlinkNode(delete);
8473 xmlFreeNode(delete);
8474 delete = NULL;
8475 }
8476}
8477
William M. Brack2f2a6632004-08-20 23:09:47 +00008478
8479/**
8480 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008481 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008482 * @ctxt: a schema validation context
8483 * @schemaLocation: an URI defining where to find the imported schema
8484 *
8485 * import a XML schema
8486 * *WARNING* this interface is highly subject to change
8487 *
8488 * Returns -1 in case of error and 1 in case of success.
8489 */
8490#if 0
8491static xmlSchemaImportPtr
8492xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8493 const xmlChar *schemaLocation)
8494{
8495 xmlSchemaImportPtr import;
8496 xmlSchemaParserCtxtPtr newctxt;
8497
8498 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8499 if (newctxt == NULL) {
8500 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8501 NULL);
8502 return (NULL);
8503 }
8504 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8505 /* Keep the same dictionnary for parsing, really */
8506 xmlDictReference(ctxt->dict);
8507 newctxt->dict = ctxt->dict;
8508 newctxt->includes = 0;
8509 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8510
8511 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8512 ctxt->userData);
8513
8514 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8515 if (import == NULL) {
8516 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8517 NULL);
8518 xmlSchemaFreeParserCtxt(newctxt);
8519 return (NULL);
8520 }
8521
8522 memset(import, 0, sizeof(xmlSchemaImport));
8523 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8524 import->schema = xmlSchemaParse(newctxt);
8525
8526 if (import->schema == NULL) {
8527 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008528 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008529 "Failed to import schema from location \"%s\".\n",
8530 schemaLocation, NULL);
8531
8532 xmlSchemaFreeParserCtxt(newctxt);
8533 /* The schemaLocation is held by the dictionary.
8534 if (import->schemaLocation != NULL)
8535 xmlFree((xmlChar *)import->schemaLocation);
8536 */
8537 xmlFree(import);
8538 return NULL;
8539 }
8540
8541 xmlSchemaFreeParserCtxt(newctxt);
8542 return import;
8543}
8544#endif
8545
8546static void
8547xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8548{
8549 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8550 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8551
8552 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8553 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8554
8555 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8556 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8557 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8558 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8559 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8560 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8561 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8562 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8563
8564 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8565 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8566 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8567 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8568 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8569 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8570}
8571
8572static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008573xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008574 xmlSchemaPtr schema,
8575 xmlNodePtr node)
8576{
8577 xmlAttrPtr attr;
8578 const xmlChar *val;
8579
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008580 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8581 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008582 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008583 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8584 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008585 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008586 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008588 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008589 if (attr != NULL) {
8590 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008592 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008593 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008594 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008595 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008596 "(qualified | unqualified)", val, NULL, NULL, NULL);
8597 }
8598 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008599
8600 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008601 if (attr != NULL) {
8602 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008604 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008606 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008607 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008608 "(qualified | unqualified)", val, NULL, NULL, NULL);
8609 }
8610 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008611
8612 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008613 if (attr != NULL) {
8614 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8615 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8616 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8617 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8618 -1,
8619 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8620 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8621 xmlSchemaPSimpleTypeErr(ctxt,
8622 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008623 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008624 "(#all | List of (extension | restriction | list | union))",
8625 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008626 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008627 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008628
8629 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008630 if (attr != NULL) {
8631 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8632 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8633 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8634 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8635 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8636 xmlSchemaPSimpleTypeErr(ctxt,
8637 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008639 "(#all | List of (extension | restriction | substitution))",
8640 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008641 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008642 }
8643}
8644
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008645/**
8646 * xmlSchemaParseSchemaTopLevel:
8647 * @ctxt: a schema validation context
8648 * @schema: the schemas
8649 * @nodes: the list of top level nodes
8650 *
8651 * Returns the internal XML Schema structure built from the resource or
8652 * NULL in case of error
8653 */
8654static void
8655xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8656 xmlSchemaPtr schema, xmlNodePtr nodes)
8657{
8658 xmlNodePtr child;
8659 xmlSchemaAnnotPtr annot;
8660
8661 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8662 return;
8663
8664 child = nodes;
8665 while ((IS_SCHEMA(child, "include")) ||
8666 (IS_SCHEMA(child, "import")) ||
8667 (IS_SCHEMA(child, "redefine")) ||
8668 (IS_SCHEMA(child, "annotation"))) {
8669 if (IS_SCHEMA(child, "annotation")) {
8670 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8671 if (schema->annot == NULL)
8672 schema->annot = annot;
8673 else
8674 xmlSchemaFreeAnnot(annot);
8675 } else if (IS_SCHEMA(child, "import")) {
8676 xmlSchemaParseImport(ctxt, schema, child);
8677 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008678 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008679 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008680 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008681 } else if (IS_SCHEMA(child, "redefine")) {
8682 TODO
8683 }
8684 child = child->next;
8685 }
8686 while (child != NULL) {
8687 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008688 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008689 child = child->next;
8690 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008691 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008692 child = child->next;
8693 } else if (IS_SCHEMA(child, "element")) {
8694 xmlSchemaParseElement(ctxt, schema, child, 1);
8695 child = child->next;
8696 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008697 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008698 child = child->next;
8699 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008700 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008701 child = child->next;
8702 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008703 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008704 child = child->next;
8705 } else if (IS_SCHEMA(child, "notation")) {
8706 xmlSchemaParseNotation(ctxt, schema, child);
8707 child = child->next;
8708 } else {
8709 xmlSchemaPErr2(ctxt, NULL, child,
8710 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008711 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008712 child->name, NULL);
8713 child = child->next;
8714 }
8715 while (IS_SCHEMA(child, "annotation")) {
8716 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8717 if (schema->annot == NULL)
8718 schema->annot = annot;
8719 else
8720 xmlSchemaFreeAnnot(annot);
8721 child = child->next;
8722 }
8723 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008724 ctxt->parentItem = NULL;
8725 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008726}
8727
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008728static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008729xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008730 xmlHashTablePtr *imports,
8731 const xmlChar *nsName)
8732{
8733 xmlSchemaImportPtr ret;
8734
8735 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008736 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008737 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008738 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008739 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8740 NULL, NULL, (xmlNodePtr) ctxt->doc,
8741 "Internal error: failed to build the import table",
8742 NULL);
8743 return (NULL);
8744 }
8745 }
8746 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8747 if (ret == NULL) {
8748 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8749 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008750 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008751 memset(ret, 0, sizeof(xmlSchemaImport));
8752 if (nsName == NULL)
8753 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008754 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008755
8756 return (ret);
8757}
8758
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008759/**
8760 * xmlSchemaNewParserCtxtUseDict:
8761 * @URL: the location of the schema
8762 * @dict: the dictionary to be used
8763 *
8764 * Create an XML Schemas parse context for that file/resource expected
8765 * to contain an XML Schemas file.
8766 *
8767 * Returns the parser context or NULL in case of error
8768 */
8769static xmlSchemaParserCtxtPtr
8770xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8771{
8772 xmlSchemaParserCtxtPtr ret;
8773 /*
8774 if (URL == NULL)
8775 return (NULL);
8776 */
8777
8778 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8779 if (ret == NULL) {
8780 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8781 NULL);
8782 return (NULL);
8783 }
8784 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8785 ret->dict = dict;
8786 xmlDictReference(dict);
8787 if (URL != NULL)
8788 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8789 ret->includes = 0;
8790 return (ret);
8791}
8792
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008793static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008794xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8795{
8796 if (vctxt->pctxt == NULL) {
8797 if (vctxt->schema != NULL)
8798 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8799 else
8800 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8801 if (vctxt->pctxt == NULL) {
8802 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8803 "failed to create a temp. parser context");
8804 return (-1);
8805 }
8806 /* TODO: Pass user data. */
8807 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8808 }
8809 return (0);
8810}
8811
8812static int
8813xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008814 xmlSchemaPtr schema,
8815 xmlNodePtr node,
8816 const xmlChar *nsName,
8817 const xmlChar *location,
8818 xmlDocPtr *doc,
8819 const xmlChar **targetNamespace,
8820 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008821{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008822 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008823 xmlParserCtxtPtr parserCtxt;
8824 xmlSchemaImportPtr import;
8825 const xmlChar *ns;
8826 xmlNodePtr root;
8827
8828 /*
8829 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8830 * <xsi:noNamespaceSchemaLocation>.
8831 */
8832 *doc = NULL;
8833 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008834 * Given that the schemaLocation [attribute] is only a hint, it is open
8835 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008836 * namespace, regardless of the ·actual value· of schemaLocation, but
8837 * such a strategy risks missing useful information when new
8838 * schemaLocations are offered.
8839 *
8840 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8841 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8842 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008843 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008844 */
8845 if (location == NULL) {
8846 /*
8847 * Schema Document Location Strategy:
8848 *
8849 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008850 * either as a resource which is an XML document or a <schema> element
8851 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008852 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008853 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008854 *
8855 * NOTE: Those stategies are not supported, so we will skip.
8856 */
8857 return (0);
8858 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008859 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008860 ns = XML_SCHEMAS_NO_NAMESPACE;
8861 else
8862 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008863
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008864 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008865 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008866 /*
8867 * There was a valid resource for the specified namespace already
8868 * defined, so skip.
8869 * TODO: This might be changed someday to allow import of
8870 * components from multiple documents for a single target namespace.
8871 */
8872 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008873 }
8874 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8875 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8876 else {
8877 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8878 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8879 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008880 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008881 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008882 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008883 * 2 Based on the location URI, identify an existing schema document,
8884 * either as a resource which is an XML document or a <schema> element
8885 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008886 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008887 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008888 * web which is or contains or references a <schema> element;
8889 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8890 *
8891 */
8892 if ((absolute == 0) && (node != NULL)) {
8893 xmlChar *base, *URI;
8894
8895 base = xmlNodeGetBase(node->doc, node);
8896 if (base == NULL) {
8897 URI = xmlBuildURI(location, node->doc->URL);
8898 } else {
8899 URI = xmlBuildURI(location, base);
8900 xmlFree(base);
8901 }
8902 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008903 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008904 xmlFree(URI);
8905 }
8906 }
8907 parserCtxt = xmlNewParserCtxt();
8908 if (parserCtxt == NULL) {
8909 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8910 "allocating a parser context", NULL);
8911 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008912 }
8913 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008914 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008915 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008916 xmlDictReference(parserCtxt->dict);
8917 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008918 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008919 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008920 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008921 * 2.1 The referent is (a fragment of) a resource which is an
8922 * XML document (see clause 1.1), which in turn corresponds to
8923 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008924 * set, which in turn corresponds to a valid schema.
8925 * TODO: What to do with the "fragment" stuff?
8926 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008927 * 2.2 The referent is a <schema> element information item in
8928 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008929 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008930 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008931 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008932 */
8933 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008934 xmlErrorPtr lerr;
8935 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008936 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008937 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008938 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008939 * If the doc is NULL and the parser error is an IO error we
8940 * will assume that the resource could not be located or accessed.
8941 *
8942 * TODO: Try to find specific error codes to react only on
8943 * localisation failures.
8944 *
8945 * TODO, FIXME: Check the spec: is a namespace added to the imported
8946 * namespaces, even if the schemaLocation did not provide
8947 * a resource? I guess so, since omitting the "schemaLocation"
8948 * attribute, imports a namespace as well.
8949 */
8950 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008951 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008952 xmlFreeParserCtxt(parserCtxt);
8953 return(0);
8954 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008955 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008956 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008957 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008958 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 xmlFreeParserCtxt(parserCtxt);
8961 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8962 }
8963 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008964
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008965 root = xmlDocGetRootElement(*doc);
8966 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008968 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008969 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008970 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008971 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008972 xmlFreeDoc(*doc);
8973 *doc = NULL;
8974 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008975 }
8976
8977 xmlSchemaCleanupDoc(pctxt, root);
8978
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008979 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008980 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008981 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008982 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008983 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008984 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985 xmlFreeDoc(*doc);
8986 *doc = NULL;
8987 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008988 }
8989 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008990 /*
8991 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 if (nsName == NULL) {
8994 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008995 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008996 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008997 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008998 "The XML schema to be imported is not expected "
8999 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009000 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009001 xmlFreeDoc(*doc);
9002 *doc = NULL;
9003 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9004 }
9005 } else {
9006 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009007 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009008 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009009 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009010 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009011 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009012 xmlFreeDoc(*doc);
9013 *doc = NULL;
9014 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9015 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009016 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009017 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009018 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009019 "The XML schema to be imported is expected to have a "
9020 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009021 "its target namespace of '%s'",
9022 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009023 xmlFreeDoc(*doc);
9024 *doc = NULL;
9025 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9026 }
9027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009028 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009029 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009030 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9031 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009032 xmlFreeDoc(*doc);
9033 *doc = NULL;
9034 return (-1);
9035 }
9036 import->schemaLocation = location;
9037 import->doc = *doc;
9038 return (0);
9039}
William M. Brack2f2a6632004-08-20 23:09:47 +00009040
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009041static void
9042xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9043 xmlSchemaPtr schema,
9044 const xmlChar *targetNamespace,
9045 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009046{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009047 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009048 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009049
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009050 /*
9051 * Save and reset the context & schema.
9052 */
9053 oldURL = pctxt->URL;
9054 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009055 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009056 oldLocImps = pctxt->localImports;
9057 pctxt->localImports = NULL;
9058 oldNumLocImps = pctxt->nbLocalImports;
9059 pctxt->nbLocalImports = 0;
9060 oldSizeLocImps = pctxt->sizeLocalImports;
9061 pctxt->sizeLocalImports = 0;
9062 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009063 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009064 xmlSchemaClearSchemaDefaults(schema);
9065 oldTNS = schema->targetNamespace;
9066 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009067 if ((targetNamespace != NULL) &&
9068 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9069 /*
9070 * We are parsing the schema for schema!
9071 */
9072 pctxt->isS4S = 1;
9073 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009074 /*
9075 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009076 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009077 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9078 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9079 /*
9080 * Restore the context & schema.
9081 */
9082 schema->flags = oldFlags;
9083 schema->targetNamespace = oldTNS;
9084 if (pctxt->localImports != NULL)
9085 xmlFree((xmlChar *) pctxt->localImports);
9086 pctxt->localImports = oldLocImps;
9087 pctxt->nbLocalImports = oldNumLocImps;
9088 pctxt->sizeLocalImports = oldSizeLocImps;
9089 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009090 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009091}
9092
William M. Brack2f2a6632004-08-20 23:09:47 +00009093/**
9094 * xmlSchemaParseImport:
9095 * @ctxt: a schema validation context
9096 * @schema: the schema being built
9097 * @node: a subtree containing XML Schema informations
9098 *
9099 * parse a XML schema Import definition
9100 * *WARNING* this interface is highly subject to change
9101 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009102 * Returns 0 in case of success, a positive error code if
9103 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009104 */
9105static int
9106xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9107 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009108{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009109 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009110 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009111 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009112 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009113 xmlAttrPtr attr;
9114 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009115 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009116
9117 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9118 return (-1);
9119
9120 /*
9121 * Check for illegal attributes.
9122 */
9123 attr = node->properties;
9124 while (attr != NULL) {
9125 if (attr->ns == NULL) {
9126 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9127 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9128 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009129 xmlSchemaPIllegalAttrErr(ctxt,
9130 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9131 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009132 }
9133 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009134 xmlSchemaPIllegalAttrErr(ctxt,
9135 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9136 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009137 }
9138 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009139 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009140 /*
9141 * Extract and validate attributes.
9142 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009143 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9144 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009145 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009146 xmlSchemaPSimpleTypeErr(ctxt,
9147 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9148 NULL, node,
9149 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009150 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009151 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9152 }
9153
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009154 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9155 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009156 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009157 xmlSchemaPSimpleTypeErr(ctxt,
9158 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9159 NULL, node,
9160 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009161 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009162 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009163 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009164 /*
9165 * And now for the children...
9166 */
9167 child = node->children;
9168 if (IS_SCHEMA(child, "annotation")) {
9169 /*
9170 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009171 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009172 */
9173 child = child->next;
9174 }
9175 if (child != NULL) {
9176 xmlSchemaPContentErr(ctxt,
9177 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9178 NULL, NULL, node, child, NULL,
9179 "(annotation?)");
9180 }
9181 /*
9182 * Apply additional constraints.
9183 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009184 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009185 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009186 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9187 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009188 * targetNamespace [attribute].
9189 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009190 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009191 xmlSchemaPCustomErr(ctxt,
9192 XML_SCHEMAP_SRC_IMPORT_1_1,
9193 NULL, NULL, node,
9194 "The value of the attribute 'namespace' must not match "
9195 "the target namespace '%s' of the importing schema",
9196 schema->targetNamespace);
9197 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9198 }
9199 } else {
9200 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009201 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009202 * <schema> must have a targetNamespace [attribute].
9203 */
9204 if (schema->targetNamespace == NULL) {
9205 xmlSchemaPCustomErr(ctxt,
9206 XML_SCHEMAP_SRC_IMPORT_1_2,
9207 NULL, NULL, node,
9208 "The attribute 'namespace' must be existent if "
9209 "the importing schema has no target namespace",
9210 NULL);
9211 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9212 }
9213 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009214 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009215 * Add the namespace to the list of locally imported namespace.
9216 */
9217 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009218 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009219 sizeof(const xmlChar*));
9220 ctxt->sizeLocalImports = 10;
9221 ctxt->nbLocalImports = 0;
9222 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9223 ctxt->sizeLocalImports *= 2;
9224 ctxt->localImports = (const xmlChar **) xmlRealloc(
9225 (xmlChar **) ctxt->localImports,
9226 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9227 }
9228 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9229 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009230 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009231 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009232 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9233 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009234 schemaLocation, &doc, &targetNamespace, 0);
9235 if (ret != 0) {
9236 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009237 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009238 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009239 } else if (doc != NULL) {
9240 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9241 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009242 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009243
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009244 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009245}
9246
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009247/**
9248 * xmlSchemaParseInclude:
9249 * @ctxt: a schema validation context
9250 * @schema: the schema being built
9251 * @node: a subtree containing XML Schema informations
9252 *
9253 * parse a XML schema Include definition
9254 *
William M. Bracke7091952004-05-11 15:09:58 +00009255 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009256 * 1 in case of success.
9257 */
9258static int
9259xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9260 xmlNodePtr node)
9261{
9262 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009263 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009264 xmlDocPtr doc = NULL;
9265 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009266 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009267 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009268 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009269 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009270
9271
9272 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9273 return (-1);
9274
9275 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009276 * Check for illegal attributes.
9277 */
9278 attr = node->properties;
9279 while (attr != NULL) {
9280 if (attr->ns == NULL) {
9281 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9282 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009283 xmlSchemaPIllegalAttrErr(ctxt,
9284 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9285 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009286 }
9287 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009288 xmlSchemaPIllegalAttrErr(ctxt,
9289 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9290 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009291 }
9292 attr = attr->next;
9293 }
9294 /*
9295 * Extract and validate attributes.
9296 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009297 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009298 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009299 * Preliminary step, extract the URI-Reference for the include and
9300 * make an URI from the base.
9301 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009302 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9303 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009304 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009305 xmlChar *uri = NULL;
9306
9307 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9308 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009309 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009310 base = xmlNodeGetBase(node->doc, node);
9311 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009312 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009313 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009314 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009315 xmlFree(base);
9316 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009317 if (uri == NULL) {
9318 xmlSchemaPErr(ctxt,
9319 node,
9320 XML_SCHEMAP_INTERNAL,
9321 "Internal error: xmlSchemaParseInclude, "
9322 "could not build an URI from the schemaLocation.\n",
9323 NULL, NULL);
9324 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009325 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009326 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9327 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009328 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009329 xmlSchemaPMissingAttrErr(ctxt,
9330 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9331 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009332 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009333 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009334 /*
9335 * And now for the children...
9336 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009337 child = node->children;
9338 while (IS_SCHEMA(child, "annotation")) {
9339 /*
9340 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009341 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009342 */
9343 child = child->next;
9344 }
9345 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009346 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009347 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9348 NULL, NULL, node, child, NULL,
9349 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009350 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009351 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009352 * Report self-inclusion.
9353 */
9354 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9355 xmlSchemaPCustomErr(ctxt,
9356 XML_SCHEMAP_SRC_INCLUDE,
9357 NULL, NULL, node,
9358 "The schema document '%s' cannot include itself.",
9359 schemaLocation);
9360 return (XML_SCHEMAP_SRC_INCLUDE);
9361 }
9362 /*
9363 * Check if this one was already processed to avoid incorrect
9364 * duplicate component errors and infinite circular inclusion.
9365 */
9366 include = schema->includes;
9367 while (include != NULL) {
9368 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9369 targetNamespace = include->origTargetNamespace;
9370 if (targetNamespace == NULL) {
9371 /*
9372 * Chameleon include: skip only if it was build for
9373 * the targetNamespace of the including schema.
9374 */
9375 if (xmlStrEqual(schema->targetNamespace,
9376 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009377 goto check_targetNamespace;
9378 }
9379 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009380 goto check_targetNamespace;
9381 }
9382 }
9383 include = include->next;
9384 }
9385 /*
9386 * First step is to parse the input document into an DOM/Infoset
9387 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009388 */
9389 parserCtxt = xmlNewParserCtxt();
9390 if (parserCtxt == NULL) {
9391 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9392 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009393 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009394 }
9395
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009396 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9397 xmlDictFree(parserCtxt->dict);
9398 parserCtxt->dict = ctxt->dict;
9399 xmlDictReference(parserCtxt->dict);
9400 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009401
9402 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009403 NULL, SCHEMAS_PARSE_OPTIONS);
9404 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009405 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009406 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009407 * TODO: It is not an error for the ·actual value· of the
9408 * schemaLocation [attribute] to fail to resolve it all, in which
9409 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009410 * So do we need a warning report here?
9411 */
9412 xmlSchemaPCustomErr(ctxt,
9413 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009414 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009415 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009416 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009417 }
9418
9419 /*
9420 * Then extract the root of the schema
9421 */
9422 root = xmlDocGetRootElement(doc);
9423 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009424 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009425 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009426 NULL, NULL, node,
9427 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009428 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009429 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009430 }
9431
9432 /*
9433 * Remove all the blank text nodes
9434 */
9435 xmlSchemaCleanupDoc(ctxt, root);
9436
9437 /*
9438 * Check the schemas top level element
9439 */
9440 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009441 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009442 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009443 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009444 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009445 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009446 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009447 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009448
William M. Brack2f2a6632004-08-20 23:09:47 +00009449 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009450 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009451 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9452 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009453 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9454 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009455check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009456 if (targetNamespace != NULL) {
9457 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009458 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009459 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009460 NULL, NULL, node,
9461 "The target namespace of the included schema "
9462 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009463 "has no target namespace",
9464 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009465 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009466 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9467 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009468 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009469 NULL, NULL, node,
9470 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009471 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009472 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009473 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009475 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009476 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009477 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009478 } else
9479 wasConvertingNs = 1;
9480 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009481
9482 if (include != NULL)
9483 goto exit;
9484
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009485 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009486 * URGENT TODO: If the schema is a chameleon-include then copy the
9487 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009488 * of those components, do nothing otherwise.
9489 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009490 * for every destinct including targetNamespace; thus not performant at
9491 * the moment.
9492 * TODO: Check when the namespace in wildcards for chameleons needs
9493 * to be converted: before we built wildcard intersections or after.
9494 */
9495 /*
9496 * Register the include.
9497 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009498 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9499 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009500 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9501 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009502 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009503 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009504 include->next = schema->includes;
9505 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009506 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009507 * TODO: Use the resolved URI for the this location, since it might
9508 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009509 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009510 include->schemaLocation = schemaLocation;
9511 include->doc = doc;
9512 /*
9513 * In case of chameleons, the original target namespace will differ
9514 * from the resulting namespace.
9515 */
9516 include->origTargetNamespace = targetNamespace;
9517 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009518#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009519 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009520 xmlGenericError(xmlGenericErrorContext,
9521 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9522 " into TNS '%s'\n", schemaLocation,
9523 targetNamespace, schema->targetNamespace);
9524 else
9525 xmlGenericError(xmlGenericErrorContext,
9526 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9527 targetNamespace);
9528#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009529 /*
9530 * Compile the included schema.
9531 */
9532 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9533
9534exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009535 /*
9536 * Remove the converting flag.
9537 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009538 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009539 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009540 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009541 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009542
9543exit_invalid:
9544 if (doc != NULL) {
9545 if (include != NULL)
9546 include->doc = NULL;
9547 xmlFreeDoc(doc);
9548 }
9549 return (ctxt->err);
9550
9551exit_failure:
9552 if (doc != NULL) {
9553 if (include != NULL)
9554 include->doc = NULL;
9555 xmlFreeDoc(doc);
9556 }
9557 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009558}
9559
9560/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009561 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009562 * @ctxt: a schema validation context
9563 * @schema: the schema being built
9564 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009565 * @type: the "compositor" type
9566 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009567 *
9568 * parse a XML schema Sequence definition
9569 * *WARNING* this interface is highly subject to change
9570 *
William M. Bracke7091952004-05-11 15:09:58 +00009571 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009572 * 1 in case of success.
9573 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009574static xmlSchemaTreeItemPtr
9575xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9576 xmlNodePtr node, xmlSchemaTypeType type,
9577 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009578{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009579 xmlSchemaModelGroupPtr item;
9580 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009581 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009582 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009583 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009584 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009585
9586 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009587 return (NULL);
9588 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009589 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009590 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009591 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9592 if (item == NULL)
9593 return (NULL);
9594
9595 if (withParticle) {
9596 if (type == XML_SCHEMA_TYPE_ALL) {
9597 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009598 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009599 } else {
9600 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009601 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9602 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9603 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009604 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009605 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9606 /*
9607 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009608 */
9609 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9610 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009611 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009612 particle->children = (xmlSchemaTreeItemPtr) item;
9613 /*
9614 * Check for illegal attributes.
9615 */
9616 attr = node->properties;
9617 while (attr != NULL) {
9618 if (attr->ns == NULL) {
9619 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9620 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9621 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009622 xmlSchemaPIllegalAttrErr(ctxt,
9623 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9624 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009625 }
9626 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009627 xmlSchemaPIllegalAttrErr(ctxt,
9628 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9629 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009630 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009631 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009632 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009633 } else {
9634 /*
9635 * Check for illegal attributes.
9636 */
9637 attr = node->properties;
9638 while (attr != NULL) {
9639 if (attr->ns == NULL) {
9640 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009641 xmlSchemaPIllegalAttrErr(ctxt,
9642 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9643 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009644 }
9645 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009646 xmlSchemaPIllegalAttrErr(ctxt,
9647 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9648 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009649 }
9650 attr = attr->next;
9651 }
9652
William M. Brack2f2a6632004-08-20 23:09:47 +00009653 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009654
William M. Brack2f2a6632004-08-20 23:09:47 +00009655 /*
9656 * Extract and validate attributes.
9657 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009658 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009659 /*
9660 * And now for the children...
9661 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009662 child = node->children;
9663 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009664 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009665 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009666 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009667 oldcontainer = ctxt->container;
9668 ctxt->container = container;
9669 if (type == XML_SCHEMA_TYPE_ALL) {
9670 xmlSchemaParticlePtr part, last = NULL;
9671
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009672 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009673 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9674 schema, child, 0);
9675 if (part != NULL) {
9676 if (part->minOccurs > 1)
9677 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009678 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009679 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9680 if (part->maxOccurs > 1)
9681 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009682 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009683 "Invalid value for maxOccurs (must be 0 or 1)",
9684 NULL);
9685 if (last == NULL)
9686 item->children = (xmlSchemaTreeItemPtr) part;
9687 else
9688 last->next = (xmlSchemaTreeItemPtr) part;
9689 last = part;
9690 }
9691 child = child->next;
9692 }
9693 if (child != NULL) {
9694 xmlSchemaPContentErr(ctxt,
9695 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9696 NULL, NULL, node, child, NULL,
9697 "(annotation?, (annotation?, element*)");
9698 }
9699 } else {
9700 /* choice + sequence */
9701 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9702
9703 while ((IS_SCHEMA(child, "element")) ||
9704 (IS_SCHEMA(child, "group")) ||
9705 (IS_SCHEMA(child, "any")) ||
9706 (IS_SCHEMA(child, "choice")) ||
9707 (IS_SCHEMA(child, "sequence"))) {
9708
9709 if (IS_SCHEMA(child, "element")) {
9710 part = (xmlSchemaTreeItemPtr)
9711 xmlSchemaParseElement(ctxt, schema, child, 0);
9712 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009713 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009714 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9715 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009716 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009717 xmlSchemaParseAny(ctxt, schema, child);
9718 } else if (IS_SCHEMA(child, "choice")) {
9719 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9720 XML_SCHEMA_TYPE_CHOICE, 1);
9721 } else if (IS_SCHEMA(child, "sequence")) {
9722 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9723 XML_SCHEMA_TYPE_SEQUENCE, 1);
9724 }
9725 if (part != NULL) {
9726 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009727 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009728 else
9729 last->next = part;
9730 last = part;
9731 }
9732 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009733 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009734 if (child != NULL) {
9735 xmlSchemaPContentErr(ctxt,
9736 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9737 NULL, NULL, node, child, NULL,
9738 "(annotation?, (element | group | choice | sequence | any)*)");
9739 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009740 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009741 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009742 if (withParticle) {
9743 if ((min == 0) && (max == 0))
9744 return (NULL);
9745 else
9746 return ((xmlSchemaTreeItemPtr) particle);
9747 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009748 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009749}
9750
9751/**
9752 * xmlSchemaParseRestriction:
9753 * @ctxt: a schema validation context
9754 * @schema: the schema being built
9755 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009756 *
9757 * parse a XML schema Restriction definition
9758 * *WARNING* this interface is highly subject to change
9759 *
9760 * Returns the type definition or NULL in case of error
9761 */
9762static xmlSchemaTypePtr
9763xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009764 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009766 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009767 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009768 char buf[30];
9769 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009770 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009771
9772 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9773 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009774 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009775 type = ctxt->ctxtType;
9776 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009777
9778 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009779 * TODO: Is the container needed at all? the anonymous
9780 * items inside should generate unique names already.
9781 */
9782 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009783 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009784 /*
9785 * Check for illegal attributes.
9786 */
9787 attr = node->properties;
9788 while (attr != NULL) {
9789 if (attr->ns == NULL) {
9790 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9791 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009792 xmlSchemaPIllegalAttrErr(ctxt,
9793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9794 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009795 }
9796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009797 xmlSchemaPIllegalAttrErr(ctxt,
9798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9799 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009800 }
9801 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009802 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009803 /*
9804 * Extract and validate attributes.
9805 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009806 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009807 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009808 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009809 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009810 /*
9811 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9812 * among its [children]), the simple type definition which is
9813 * the {content type} of the type definition ·resolved· to by
9814 * the ·actual value· of the base [attribute]"
9815 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009816 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009817 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009818 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009819 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009820 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009821 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009822 XML_SCHEMAP_S4S_ATTR_MISSING,
9823 type, node, "base", NULL);
9824 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009825 /*
9826 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009827 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009828 child = node->children;
9829 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009830 /*
9831 * Add the annotation to the simple type ancestor.
9832 */
9833 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9834 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009835 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009836 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009837 oldcontainer = ctxt->container;
9838 ctxt->container = container;
9839 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9840 /*
9841 * Corresponds to <simpleType><restriction><simpleType>.
9842 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009843 if (IS_SCHEMA(child, "simpleType")) {
9844 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009845 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009846 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009847 * Either the base [attribute] or the simpleType [child] of the
9848 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009849 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009850 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009851 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009852 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009853 "The attribute 'base' and the <simpleType> child are "
9854 "mutually exclusive", NULL);
9855 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009856 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009857 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009858 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009859 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009860 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009861 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009862 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9863 NULL, NULL, node, child,
9864 "Either the attribute 'base' or a <simpleType> child "
9865 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009866 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009867 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9868 /*
9869 * Corresponds to <complexType><complexContent><restriction>...
9870 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009871 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009872 * Model groups <all>, <choice> and <sequence>.
9873 */
9874 if (IS_SCHEMA(child, "all")) {
9875 type->subtypes = (xmlSchemaTypePtr)
9876 xmlSchemaParseModelGroup(ctxt, schema, child,
9877 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009878 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009879 } else if (IS_SCHEMA(child, "choice")) {
9880 type->subtypes = (xmlSchemaTypePtr)
9881 xmlSchemaParseModelGroup(ctxt,
9882 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9883 child = child->next;
9884 } else if (IS_SCHEMA(child, "sequence")) {
9885 type->subtypes = (xmlSchemaTypePtr)
9886 xmlSchemaParseModelGroup(ctxt, schema, child,
9887 XML_SCHEMA_TYPE_SEQUENCE, 1);
9888 child = child->next;
9889 /*
9890 * Model group reference <group>.
9891 */
9892 } else if (IS_SCHEMA(child, "group")) {
9893 type->subtypes = (xmlSchemaTypePtr)
9894 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9895 child = child->next;
9896 }
9897 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009898 /*
9899 * Corresponds to <complexType><simpleContent><restriction>...
9900 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009901 * "1.1 the simple type definition corresponding to the <simpleType>
9902 * among the [children] of <restriction> if there is one;"
9903 */
9904 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009905 /*
9906 * We will store the to-be-restricted simple type in
9907 * type->contentTypeDef *temporarily*.
9908 */
9909 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009910 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009911 if ( type->contentTypeDef == NULL)
9912 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009913 child = child->next;
9914 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009915 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009916
9917 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009918 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009919 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009920 /*
9921 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009922 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009923 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009924
Daniel Veillard01fa6152004-06-29 17:04:39 +00009925 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009926 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009927 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009928 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009929 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9930 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009931 * *Single Facet Value*
9932 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009933 while ((IS_SCHEMA(child, "minInclusive")) ||
9934 (IS_SCHEMA(child, "minExclusive")) ||
9935 (IS_SCHEMA(child, "maxInclusive")) ||
9936 (IS_SCHEMA(child, "maxExclusive")) ||
9937 (IS_SCHEMA(child, "totalDigits")) ||
9938 (IS_SCHEMA(child, "fractionDigits")) ||
9939 (IS_SCHEMA(child, "pattern")) ||
9940 (IS_SCHEMA(child, "enumeration")) ||
9941 (IS_SCHEMA(child, "whiteSpace")) ||
9942 (IS_SCHEMA(child, "length")) ||
9943 (IS_SCHEMA(child, "maxLength")) ||
9944 (IS_SCHEMA(child, "minLength"))) {
9945 facet = xmlSchemaParseFacet(ctxt, schema, child);
9946 if (facet != NULL) {
9947 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009948 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009949 else
9950 lastfacet->next = facet;
9951 lastfacet = facet;
9952 lastfacet->next = NULL;
9953 }
9954 child = child->next;
9955 }
9956 /*
9957 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009958 */
9959 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009960 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9961
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009962 facet = type->facets;
9963 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009964 facetLink = (xmlSchemaFacetLinkPtr)
9965 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009966 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009967 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009968 xmlFree(facetLink);
9969 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009970 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009971 facetLink->facet = facet;
9972 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009973 if (lastFacetLink == NULL)
9974 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009975 else
9976 lastFacetLink->next = facetLink;
9977 lastFacetLink = facetLink;
9978 facet = facet->next;
9979 } while (facet != NULL);
9980 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009981 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009982 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9983 /*
9984 * Attribute uses/declarations.
9985 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009986 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009987 /*
9988 * Attribute wildcard.
9989 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009990 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009991 type->attributeWildcard =
9992 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009993 child = child->next;
9994 }
9995 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009996 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009997 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9998 xmlSchemaPContentErr(ctxt,
9999 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010000 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010001 "annotation?, (group | all | choice | sequence)?, "
10002 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010003 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010004 xmlSchemaPContentErr(ctxt,
10005 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010006 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010007 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10008 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10009 "length | minLength | maxLength | enumeration | whiteSpace | "
10010 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10011 } else {
10012 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010013 xmlSchemaPContentErr(ctxt,
10014 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010015 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010016 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10017 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10018 "length | minLength | maxLength | enumeration | whiteSpace | "
10019 "pattern)*))");
10020 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010021 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010022 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010023 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010024}
10025
10026/**
10027 * xmlSchemaParseExtension:
10028 * @ctxt: a schema validation context
10029 * @schema: the schema being built
10030 * @node: a subtree containing XML Schema informations
10031 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010032 * Parses an <extension>, which is found inside a
10033 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010034 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010035 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010036 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010037 */
10038static xmlSchemaTypePtr
10039xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010040 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010041{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010042 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010043 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010044 char buf[30];
10045 const xmlChar *oldcontainer, *container;
10046 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010047
10048 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10049 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010050 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010051 type = ctxt->ctxtType;
10052 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010053
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010054 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10055 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10056 /*
10057 * Check for illegal attributes.
10058 */
10059 attr = node->properties;
10060 while (attr != NULL) {
10061 if (attr->ns == NULL) {
10062 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10063 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010064 xmlSchemaPIllegalAttrErr(ctxt,
10065 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10066 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010067 }
10068 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010069 xmlSchemaPIllegalAttrErr(ctxt,
10070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10071 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010072 }
10073 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010074 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010075
10076 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010077
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010078 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010079 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010080 */
10081 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010082 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10083 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010084 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010085 XML_SCHEMAP_S4S_ATTR_MISSING,
10086 NULL, node, "base", NULL);
10087 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010088 /*
10089 * And now for the children...
10090 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010091 child = node->children;
10092 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010093 /*
10094 * Add the annotation to the type ancestor.
10095 */
10096 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10097 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010098 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010099 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010100 oldcontainer = ctxt->container;
10101 ctxt->container = container;
10102 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10103 /*
10104 * Corresponds to <complexType><complexContent><extension>... and:
10105 *
10106 * Model groups <all>, <choice>, <sequence> and <group>.
10107 */
10108 if (IS_SCHEMA(child, "all")) {
10109 type->subtypes = (xmlSchemaTypePtr)
10110 xmlSchemaParseModelGroup(ctxt, schema,
10111 child, XML_SCHEMA_TYPE_ALL, 1);
10112 child = child->next;
10113 } else if (IS_SCHEMA(child, "choice")) {
10114 type->subtypes = (xmlSchemaTypePtr)
10115 xmlSchemaParseModelGroup(ctxt, schema,
10116 child, XML_SCHEMA_TYPE_CHOICE, 1);
10117 child = child->next;
10118 } else if (IS_SCHEMA(child, "sequence")) {
10119 type->subtypes = (xmlSchemaTypePtr)
10120 xmlSchemaParseModelGroup(ctxt, schema,
10121 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10122 child = child->next;
10123 } else if (IS_SCHEMA(child, "group")) {
10124 type->subtypes = (xmlSchemaTypePtr)
10125 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10126 child = child->next;
10127 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010128 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010129 if (child != NULL) {
10130 /*
10131 * Attribute uses/declarations.
10132 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010133 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010134 /*
10135 * Attribute wildcard.
10136 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010137 if (IS_SCHEMA(child, "anyAttribute")) {
10138 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010139 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10140 child = child->next;
10141 }
10142 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010143 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010144 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10145 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010146 xmlSchemaPContentErr(ctxt,
10147 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010148 NULL, NULL, node, child, NULL,
10149 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010150 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010151 } else {
10152 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010153 xmlSchemaPContentErr(ctxt,
10154 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010155 NULL, NULL, node, child, NULL,
10156 "(annotation?, ((attribute | attributeGroup)*, "
10157 "anyAttribute?))");
10158 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010159 }
10160 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010161 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010162}
10163
10164/**
10165 * xmlSchemaParseSimpleContent:
10166 * @ctxt: a schema validation context
10167 * @schema: the schema being built
10168 * @node: a subtree containing XML Schema informations
10169 *
10170 * parse a XML schema SimpleContent definition
10171 * *WARNING* this interface is highly subject to change
10172 *
10173 * Returns the type definition or NULL in case of error
10174 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010175static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010176xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10177 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010178{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010179 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010180 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010181 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010182
10183 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010184 return (-1);
10185 /* Not a component, don't create it. */
10186 type = ctxt->ctxtType;
10187 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10188 /*
10189 * Check for illegal attributes.
10190 */
10191 attr = node->properties;
10192 while (attr != NULL) {
10193 if (attr->ns == NULL) {
10194 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010195 xmlSchemaPIllegalAttrErr(ctxt,
10196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10197 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010198 }
10199 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010200 xmlSchemaPIllegalAttrErr(ctxt,
10201 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10202 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010203 }
10204 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010205 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010206
10207 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010208
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010209 /*
10210 * And now for the children...
10211 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010212 child = node->children;
10213 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010214 /*
10215 * Add the annotation to the complex type ancestor.
10216 */
10217 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10218 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010219 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010220 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010221 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010222 xmlSchemaParseRestriction(ctxt, schema, child,
10223 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010225 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010226 xmlSchemaParseExtension(ctxt, schema, child,
10227 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010228 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010229 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010230 if (child != NULL) {
10231 xmlSchemaPContentErr(ctxt,
10232 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010233 NULL, NULL, node, child, NULL,
10234 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010235 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010236 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010237}
10238
10239/**
10240 * xmlSchemaParseComplexContent:
10241 * @ctxt: a schema validation context
10242 * @schema: the schema being built
10243 * @node: a subtree containing XML Schema informations
10244 *
10245 * parse a XML schema ComplexContent definition
10246 * *WARNING* this interface is highly subject to change
10247 *
10248 * Returns the type definition or NULL in case of error
10249 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010250static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010251xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10252 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010253{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010254 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010255 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010256 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010257
10258 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010259 return (-1);
10260 /* Not a component, don't create it. */
10261 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010262 /*
10263 * Check for illegal attributes.
10264 */
10265 attr = node->properties;
10266 while (attr != NULL) {
10267 if (attr->ns == NULL) {
10268 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010269 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010270 {
10271 xmlSchemaPIllegalAttrErr(ctxt,
10272 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10273 NULL, NULL, attr);
10274 }
10275 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10276 xmlSchemaPIllegalAttrErr(ctxt,
10277 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10278 NULL, NULL, attr);
10279 }
10280 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010281 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010282
10283 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10284
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010285 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010286 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010287 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010288 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10289 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10290 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010291 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010292 child = node->children;
10293 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010294 /*
10295 * Add the annotation to the complex type ancestor.
10296 */
10297 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10298 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010299 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010300 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010301 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010302 xmlSchemaParseRestriction(ctxt, schema, child,
10303 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010304 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010305 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010306 xmlSchemaParseExtension(ctxt, schema, child,
10307 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010308 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010309 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010310 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010311 xmlSchemaPContentErr(ctxt,
10312 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10313 NULL, NULL, node, child,
10314 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010315 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010316 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010317}
10318
10319/**
10320 * xmlSchemaParseComplexType:
10321 * @ctxt: a schema validation context
10322 * @schema: the schema being built
10323 * @node: a subtree containing XML Schema informations
10324 *
10325 * parse a XML schema Complex Type definition
10326 * *WARNING* this interface is highly subject to change
10327 *
10328 * Returns the type definition or NULL in case of error
10329 */
10330static xmlSchemaTypePtr
10331xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010332 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010333{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010334 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010335 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010336 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010337 xmlAttrPtr attr;
10338 const xmlChar *attrValue;
10339 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010340 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010341 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010342
Daniel Veillard4255d502002-04-16 15:50:10 +000010343
10344 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10345 return (NULL);
10346
Daniel Veillard01fa6152004-06-29 17:04:39 +000010347 ctxtType = ctxt->ctxtType;
10348
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010349 if (topLevel) {
10350 attr = xmlSchemaGetPropNode(node, "name");
10351 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010352 xmlSchemaPMissingAttrErr(ctxt,
10353 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010354 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010355 } else if (xmlSchemaPValAttrNode(ctxt,
10356 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010357 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10358 return (NULL);
10359 }
10360 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010361
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010362 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010363 /*
10364 * Parse as local complex type definition.
10365 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010366 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010367 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10368 if (type == NULL)
10369 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010370 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010371 type->node = node;
10372 type->type = XML_SCHEMA_TYPE_COMPLEX;
10373 /*
10374 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010375 */
10376 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010377 /*
10378 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010379 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010380 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010381 if (type == NULL)
10382 return (NULL);
10383 type->node = node;
10384 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010385 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010386 }
10387 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010388 /*
10389 * Handle attributes.
10390 */
10391 attr = node->properties;
10392 while (attr != NULL) {
10393 if (attr->ns == NULL) {
10394 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10395 /*
10396 * Attribute "id".
10397 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010398 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10399 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010400 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10401 /*
10402 * Attribute "mixed".
10403 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010404 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010405 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010406 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10407 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010408 /*
10409 * Attributes of global complex type definitions.
10410 */
10411 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10412 /* Pass. */
10413 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10414 /*
10415 * Attribute "abstract".
10416 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010417 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10418 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010419 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10420 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10421 /*
10422 * Attribute "final".
10423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010424 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010425 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010426 if (xmlSchemaPValAttrBlockFinal(attrValue,
10427 &(type->flags),
10428 -1,
10429 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10430 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10431 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010432 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010433 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010434 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010435 type, (xmlNodePtr) attr, NULL,
10436 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010437 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010438 } else
10439 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010440 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10441 /*
10442 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010443 */
10444 attrValue = xmlSchemaGetNodeContent(ctxt,
10445 (xmlNodePtr) attr);
10446 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010447 -1,
10448 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010449 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010450 -1, -1, -1) != 0) {
10451 xmlSchemaPSimpleTypeErr(ctxt,
10452 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010453 type, (xmlNodePtr) attr, NULL,
10454 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010455 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010456 } else
10457 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010458 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010459 xmlSchemaPIllegalAttrErr(ctxt,
10460 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010461 &des, type, attr);
10462 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010463 } else {
10464 xmlSchemaPIllegalAttrErr(ctxt,
10465 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010466 &des, type, attr);
10467 }
10468 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010469 xmlSchemaPIllegalAttrErr(ctxt,
10470 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10471 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010472 }
10473 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010475 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010476 /*
10477 * Apply default "block" values.
10478 */
10479 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10480 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10481 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10482 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10483 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010484 if (! final) {
10485 /*
10486 * Apply default "block" values.
10487 */
10488 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10489 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10490 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10491 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10492 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010493 /*
10494 * And now for the children...
10495 */
10496 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010497 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010498 child = node->children;
10499 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010500 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10501 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010502 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010503 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010504 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010505 /*
10506 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010507 * Specifying mixed='true' when the <simpleContent>
10508 * alternative is chosen has no effect
10509 */
William M. Bracke7091952004-05-11 15:09:58 +000010510 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10511 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010512 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010513 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010514 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010515 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10516 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010517 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010518 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010519 /*
10520 * SPEC
10521 * "...the third alternative (neither <simpleContent> nor
10522 * <complexContent>) is chosen. This case is understood as shorthand
10523 * for complex content restricting the ·ur-type definition·, and the
10524 * details of the mappings should be modified as necessary.
10525 */
10526 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10527 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010528 /*
10529 * Parse model groups.
10530 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010531 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010532 type->subtypes = (xmlSchemaTypePtr)
10533 xmlSchemaParseModelGroup(ctxt, schema, child,
10534 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010535 child = child->next;
10536 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010537 type->subtypes = (xmlSchemaTypePtr)
10538 xmlSchemaParseModelGroup(ctxt, schema, child,
10539 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010540 child = child->next;
10541 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010542 type->subtypes = (xmlSchemaTypePtr)
10543 xmlSchemaParseModelGroup(ctxt, schema, child,
10544 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010545 child = child->next;
10546 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010547 type->subtypes = (xmlSchemaTypePtr)
10548 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010549 child = child->next;
10550 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010551 /*
10552 * Parse attribute decls/refs.
10553 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010554 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010555 /*
10556 * Parse attribute wildcard.
10557 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010558 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010559 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10560 child = child->next;
10561 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010562 }
10563 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010564 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010565 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010566 &des, type, node, child,
10567 NULL, "(annotation?, (simpleContent | complexContent | "
10568 "((group | all | choice | sequence)?, ((attribute | "
10569 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010570 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010571 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010572 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010573 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010574 return (type);
10575}
10576
Daniel Veillard4255d502002-04-16 15:50:10 +000010577/**
10578 * xmlSchemaParseSchema:
10579 * @ctxt: a schema validation context
10580 * @node: a subtree containing XML Schema informations
10581 *
10582 * parse a XML schema definition from a node set
10583 * *WARNING* this interface is highly subject to change
10584 *
10585 * Returns the internal XML Schema structure built from the resource or
10586 * NULL in case of error
10587 */
10588static xmlSchemaPtr
10589xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10590{
10591 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010592 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010593 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010594 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010595
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010596 /*
10597 * This one is called by xmlSchemaParse only and is used if
10598 * the schema to be parsed was specified via the API; i.e. not
10599 * automatically by the validated instance document.
10600 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010601 if ((ctxt == NULL) || (node == NULL))
10602 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010603 nberrors = ctxt->nberrors;
10604 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010605 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010606 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010607 xmlSchemaImportPtr import;
10608
Daniel Veillard4255d502002-04-16 15:50:10 +000010609 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010610 if (schema == NULL)
10611 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010612 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010613 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010614 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010615 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10616 /*
10617 * TODO: Should we proceed with an invalid target namespace?
10618 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010619 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010620 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10621 /*
10622 * We are parsing the schema for schema!
10623 */
10624 ctxt->isS4S = 1;
10625 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010626 } else {
10627 schema->targetNamespace = NULL;
10628 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010629 /*
10630 * Add the current ns name and location to the import table;
10631 * this is needed to have a consistent mechanism, regardless
10632 * if all schemata are constructed dynamically fired by the
10633 * instance or if the schema to be used was specified via
10634 * the API.
10635 */
10636 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10637 schema->targetNamespace);
10638 if (import == NULL) {
10639 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10640 NULL, NULL, (xmlNodePtr) ctxt->doc,
10641 "Internal error: xmlSchemaParseSchema, "
10642 "failed to add an import entry", NULL);
10643 xmlSchemaFree(schema);
10644 schema = NULL;
10645 return (NULL);
10646 }
10647 import->schemaLocation = ctxt->URL;
10648 /*
10649 * NOTE: We won't set the doc here, otherwise it will be freed
10650 * if the import struct is freed.
10651 * import->doc = ctxt->doc;
10652 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010653 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010654 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10655 } else {
10656 xmlDocPtr doc;
10657
10658 doc = node->doc;
10659
10660 if ((doc != NULL) && (doc->URL != NULL)) {
10661 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10662 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010663 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010664 } else {
10665 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10666 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010667 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010668 }
10669 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010670 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010671 if (ctxt->nberrors != 0) {
10672 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010673 xmlSchemaFree(schema);
10674 schema = NULL;
10675 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010676 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010677 if (schema != NULL)
10678 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010679 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010680#ifdef DEBUG
10681 if (schema == NULL)
10682 xmlGenericError(xmlGenericErrorContext,
10683 "xmlSchemaParse() failed\n");
10684#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010685 return (schema);
10686}
10687
10688/************************************************************************
10689 * *
10690 * Validating using Schemas *
10691 * *
10692 ************************************************************************/
10693
10694/************************************************************************
10695 * *
10696 * Reading/Writing Schemas *
10697 * *
10698 ************************************************************************/
10699
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010700#if 0 /* Will be enabled if it is clear what options are needed. */
10701/**
10702 * xmlSchemaParserCtxtSetOptions:
10703 * @ctxt: a schema parser context
10704 * @options: a combination of xmlSchemaParserOption
10705 *
10706 * Sets the options to be used during the parse.
10707 *
10708 * Returns 0 in case of success, -1 in case of an
10709 * API error.
10710 */
10711static int
10712xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10713 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010714
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010715{
10716 int i;
10717
10718 if (ctxt == NULL)
10719 return (-1);
10720 /*
10721 * WARNING: Change the start value if adding to the
10722 * xmlSchemaParseOption.
10723 */
10724 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10725 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010726 return (-1);
10727 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010728 }
10729 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010730 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010731}
10732
10733/**
10734 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010735 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010736 *
10737 * Returns the option combination of the parser context.
10738 */
10739static int
10740xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010741
10742{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010743 if (ctxt == NULL)
10744 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010745 else
10746 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010747}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010748#endif
10749
Daniel Veillard4255d502002-04-16 15:50:10 +000010750/**
10751 * xmlSchemaNewParserCtxt:
10752 * @URL: the location of the schema
10753 *
10754 * Create an XML Schemas parse context for that file/resource expected
10755 * to contain an XML Schemas file.
10756 *
10757 * Returns the parser context or NULL in case of error
10758 */
10759xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010760xmlSchemaNewParserCtxt(const char *URL)
10761{
Daniel Veillard4255d502002-04-16 15:50:10 +000010762 xmlSchemaParserCtxtPtr ret;
10763
10764 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010765 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010766
10767 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10768 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010769 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010770 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010771 return (NULL);
10772 }
10773 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010774 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010775 ret->dict = xmlDictCreate();
10776 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010777 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010778 return (ret);
10779}
10780
10781/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010782 * xmlSchemaNewMemParserCtxt:
10783 * @buffer: a pointer to a char array containing the schemas
10784 * @size: the size of the array
10785 *
10786 * Create an XML Schemas parse context for that memory buffer expected
10787 * to contain an XML Schemas file.
10788 *
10789 * Returns the parser context or NULL in case of error
10790 */
10791xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010792xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10793{
Daniel Veillard6045c902002-10-09 21:13:59 +000010794 xmlSchemaParserCtxtPtr ret;
10795
10796 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010797 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010798
10799 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10800 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010801 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010802 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010803 return (NULL);
10804 }
10805 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10806 ret->buffer = buffer;
10807 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010808 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010809 return (ret);
10810}
10811
10812/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010813 * xmlSchemaNewDocParserCtxt:
10814 * @doc: a preparsed document tree
10815 *
10816 * Create an XML Schemas parse context for that document.
10817 * NB. The document may be modified during the parsing process.
10818 *
10819 * Returns the parser context or NULL in case of error
10820 */
10821xmlSchemaParserCtxtPtr
10822xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10823{
10824 xmlSchemaParserCtxtPtr ret;
10825
10826 if (doc == NULL)
10827 return (NULL);
10828
10829 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10830 if (ret == NULL) {
10831 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10832 NULL);
10833 return (NULL);
10834 }
10835 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10836 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010837 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010838 /* The application has responsibility for the document */
10839 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010840
10841 return (ret);
10842}
10843
10844/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010845 * xmlSchemaFreeParserCtxt:
10846 * @ctxt: the schema parser context
10847 *
10848 * Free the resources associated to the schema parser context
10849 */
10850void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010851xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10852{
Daniel Veillard4255d502002-04-16 15:50:10 +000010853 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010854 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010855 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010856 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010857 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010858 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010859 xmlFree(ctxt->assemble);
10860 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010861 if (ctxt->vctxt != NULL) {
10862 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10863 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010864 if (ctxt->localImports != NULL)
10865 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010866 if (ctxt->substGroups != NULL)
10867 xmlHashFree(ctxt->substGroups,
10868 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010869 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010870 xmlFree(ctxt);
10871}
10872
10873/************************************************************************
10874 * *
10875 * Building the content models *
10876 * *
10877 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010878
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010879static void
10880xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010881 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010882{
10883 xmlAutomataStatePtr start;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010884 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010885 xmlAutomataStatePtr end;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010886 xmlSchemaSubstGroupPtr substGroup;
10887 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010888
10889 elemDecl = (xmlSchemaElementPtr) particle->children;
10890 /*
10891 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010892 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010893 start = pctxt->state;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010894 end = xmlAutomataNewState(pctxt->am);
10895 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10896 if (substGroup == NULL) {
10897 xmlSchemaPErr(pctxt, GET_NODE(particle),
10898 XML_SCHEMAP_INTERNAL,
10899 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10900 "declaration is marked having a subst. group but none "
10901 "available.\n", elemDecl->name, NULL);
10902 return;
10903 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010904 if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010905 /*
10906 * NOTE that we put the declaration in, even if it's abstract,
10907 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010908 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010909 xmlAutomataNewTransition2(pctxt->am,
10910 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010911 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10912 /*
10913 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010914 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010915 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010916 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10917 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010918 xmlAutomataNewTransition2(pctxt->am,
10919 start, NULL,
10920 member->name, member->targetNamespace, member),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010921 end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010922 }
10923 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010924 int counter;
10925 xmlAutomataStatePtr hop;
10926 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10927 UNBOUNDED : particle->maxOccurs - 1;
10928 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10929
10930 counter =
10931 xmlAutomataNewCounter(pctxt->am, minOccurs,
10932 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010933 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010934
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010935 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010936 xmlAutomataNewTransition2(pctxt->am,
10937 start, NULL,
10938 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010939 hop);
10940 /*
10941 * Add subst. group members.
10942 */
10943 for (i = 0; i < substGroup->members->nbItems; i++) {
10944 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10945 xmlAutomataNewEpsilon(pctxt->am,
10946 xmlAutomataNewTransition2(pctxt->am,
10947 start, NULL,
10948 member->name, member->targetNamespace, member),
10949 hop);
10950 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010951 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10952 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10953 }
10954 if (particle->minOccurs == 0)
10955 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010956 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010957}
10958
10959static void
10960xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10961 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010962{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010963 if (((xmlSchemaElementPtr) particle->children)->flags &
10964 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010965 /*
10966 * Substitution groups.
10967 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010968 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010969 } else {
10970 xmlSchemaElementPtr elemDecl;
10971 xmlAutomataStatePtr start;
10972
10973 elemDecl = (xmlSchemaElementPtr) particle->children;
10974
10975 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010976 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010977 if (particle->maxOccurs == 1) {
10978 start = ctxt->state;
10979 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10980 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10981 } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) {
10982 /* Special case. */
10983 start = ctxt->state;
10984 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10985 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010986 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010987 } else {
10988 int counter;
10989 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10990 UNBOUNDED : particle->maxOccurs - 1;
10991 int minOccurs = particle->minOccurs < 1 ?
10992 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010993
10994 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010995 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10996 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10997 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10998 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
10999 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11000 NULL, counter);
11001 }
11002 if (particle->minOccurs == 0)
11003 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11004 }
11005}
11006
Daniel Veillard4255d502002-04-16 15:50:10 +000011007/**
11008 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011009 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011010 * @particle: the particle component
11011 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011012 *
11013 * Generate the automata sequence needed for that type
11014 */
11015static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011016xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011017 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011018 const xmlChar * name)
11019{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011020 if (particle == NULL) {
11021 xmlSchemaPErr(ctxt, NULL,
11022 XML_SCHEMAP_INTERNAL,
11023 "Internal error: xmlSchemaBuildAContentModel, "
11024 "particle is NULL.\n", NULL, NULL);
11025 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011026 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011027 if (particle->children == NULL) {
11028 xmlSchemaPErr(ctxt, GET_NODE(particle),
11029 XML_SCHEMAP_INTERNAL,
11030 "Internal error: xmlSchemaBuildAContentModel, "
11031 "no term on particle.\n", NULL, NULL);
11032 return;
11033 }
11034
11035 switch (particle->children->type) {
11036 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011037 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011038 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011039 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011040
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011041 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011042
Daniel Veillardc0826a72004-08-10 14:17:33 +000011043 start = ctxt->state;
11044 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011045
11046 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011047 if (wild->any == 1) {
11048 /*
11049 * We need to add both transitions:
11050 *
11051 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011052 */
11053 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011054 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011055 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011056 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11057 /*
11058 * 2. the {"*"} for elements in no namespace.
11059 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011060 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011061 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011062 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011063 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11064
11065 } else if (wild->nsSet != NULL) {
11066 ns = wild->nsSet;
11067 do {
11068 ctxt->state = start;
11069 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011070 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011071 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11072 ns = ns->next;
11073 } while (ns != NULL);
11074
11075 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011076
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011077 /*
11078 * Lead nodes with the negated namespace to the sink-state
11079 * {"*", "##other"}.
11080 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011081 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011082 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011083 /*
11084 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011085 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011086 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011087 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011088 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011089 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011090 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011091 } else {
11092 int counter;
11093 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011094 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011095 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011096 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011097 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011098
Daniel Veillardc0826a72004-08-10 14:17:33 +000011099 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011100 hop = xmlAutomataNewState(ctxt->am);
11101 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011102 ctxt->state =
11103 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011104 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011105 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011106 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011107 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011108 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011109 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011110 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011111 ns = wild->nsSet;
11112 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011113 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011114 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011115 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011116 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11117 ns = ns->next;
11118 } while (ns != NULL);
11119
11120 } else if (wild->negNsSet != NULL) {
11121 xmlAutomataStatePtr deadEnd;
11122
11123 deadEnd = xmlAutomataNewState(ctxt->am);
11124 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011125 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011126 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011127 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011128 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011129 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011130 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11131 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11132 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011133 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011134 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011135 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011136 ctxt->state = end;
11137 break;
11138 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011139 case XML_SCHEMA_TYPE_ELEMENT:
11140 xmlSchemaBuildContentModelForElement(ctxt, particle);
11141 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011142 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011143 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011144
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011145 /*
11146 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011147 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011148 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011149 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11150 sub = particle->children->children;
11151 while (sub != NULL) {
11152 xmlSchemaBuildAContentModel(ctxt,
11153 (xmlSchemaParticlePtr) sub, name);
11154 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011155 }
11156 } else {
11157 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011158
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011159 if (particle->maxOccurs >= UNBOUNDED) {
11160 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011161 xmlAutomataStatePtr tmp;
11162 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011163
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011164 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011165 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011166 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011167
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011168 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011169 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011170
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011171 sub = particle->children->children;
11172 while (sub != NULL) {
11173 xmlSchemaBuildAContentModel(ctxt,
11174 (xmlSchemaParticlePtr) sub, name);
11175 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011176 }
11177 tmp = ctxt->state;
11178 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11179 oldstate, counter);
11180 ctxt->state =
11181 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11182 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011183
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011184 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011185 sub = particle->children->children;
11186 while (sub != NULL) {
11187 xmlSchemaBuildAContentModel(ctxt,
11188 (xmlSchemaParticlePtr) sub, name);
11189 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011190 }
11191 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11192 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011193 if (particle->minOccurs == 0) {
11194 xmlAutomataNewEpsilon(ctxt->am,
11195 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011196 }
11197 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011198 } else if ((particle->maxOccurs > 1)
11199 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011200 xmlAutomataStatePtr tmp;
11201 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011202
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011203 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011204 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011205 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011206
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011207 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011208 particle->minOccurs - 1,
11209 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011210
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011211 sub = particle->children->children;
11212 while (sub != NULL) {
11213 xmlSchemaBuildAContentModel(ctxt,
11214 (xmlSchemaParticlePtr) sub, name);
11215 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011216 }
11217 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011218 xmlAutomataNewCountedTrans(ctxt->am,
11219 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011220 ctxt->state =
11221 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11222 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011223 if (particle->minOccurs == 0) {
11224 xmlAutomataNewEpsilon(ctxt->am,
11225 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011226 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011227 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011228 sub = particle->children->children;
11229 while (sub != NULL) {
11230 xmlSchemaBuildAContentModel(ctxt,
11231 (xmlSchemaParticlePtr) sub, name);
11232 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011233 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011234 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011235 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11236 ctxt->state);
11237 }
11238 }
11239 }
11240 break;
11241 }
11242 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011243 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011244 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011245
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011246 start = ctxt->state;
11247 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011248
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011249 /*
11250 * iterate over the subtypes and remerge the end with an
11251 * epsilon transition
11252 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011253 if (particle->maxOccurs == 1) {
11254 sub = particle->children->children;
11255 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011256 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011257 xmlSchemaBuildAContentModel(ctxt,
11258 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011259 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011260 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011261 }
11262 } else {
11263 int counter;
11264 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011265 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11266 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011267 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011268 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011269
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011270 /*
11271 * use a counter to keep track of the number of transtions
11272 * which went through the choice.
11273 */
11274 counter =
11275 xmlAutomataNewCounter(ctxt->am, minOccurs,
11276 maxOccurs);
11277 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011278
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011279 sub = particle->children->children;
11280 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011281 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011282 xmlSchemaBuildAContentModel(ctxt,
11283 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011284 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011285 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011286 }
11287 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11288 counter);
11289 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11290 counter);
11291 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011292 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011293 xmlAutomataNewEpsilon(ctxt->am, start, end);
11294 }
11295 ctxt->state = end;
11296 break;
11297 }
11298 case XML_SCHEMA_TYPE_ALL:{
11299 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011300 xmlSchemaParticlePtr sub;
11301 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011302 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011303
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011304 sub = (xmlSchemaParticlePtr) particle->children->children;
11305 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011306 break;
11307 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011308 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011309 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011310
11311 elemDecl = (xmlSchemaElementPtr) sub->children;
11312 if (elemDecl == NULL) {
11313 xmlSchemaPErr(ctxt, NULL,
11314 XML_SCHEMAP_INTERNAL,
11315 "Internal error: xmlSchemaBuildAContentModel, "
11316 "<element> particle a NULL term.\n", NULL, NULL);
11317 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011318 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011319 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011320 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011321 * {particles} of the group must be 0 or 1; this is
11322 * already ensured during the parse of the content of
11323 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011324 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011325 if ((sub->minOccurs == 1) &&
11326 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011327 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011328 ctxt->state,
11329 elemDecl->name,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011330 elemDecl->targetNamespace,
11331 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011332 } else if ((sub->minOccurs == 0) &&
11333 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011334
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011335 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011336 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011337 elemDecl->name,
11338 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011339 0,
11340 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011341 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011342 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011343 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011344 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011345 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011346 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011347 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011348 break;
11349 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011350 default:
11351 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011352 "Internal error: xmlSchemaBuildAContentModel, found "
11353 "unexpected term of type %d in content model of complex "
11354 "type '%s'.\n",
11355 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011356 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011357 }
11358}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011359
Daniel Veillard4255d502002-04-16 15:50:10 +000011360/**
11361 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011362 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011363 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011364 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011365 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011366 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011367 */
11368static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011369xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011370 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011371 const xmlChar * name)
11372{
Daniel Veillard4255d502002-04-16 15:50:10 +000011373 xmlAutomataStatePtr start;
11374
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011375 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11376 (type->contModel != NULL) ||
11377 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11378 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011379 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011380
11381#ifdef DEBUG_CONTENT
11382 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011383 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011384#endif
11385
Daniel Veillard4255d502002-04-16 15:50:10 +000011386 ctxt->am = xmlNewAutomata();
11387 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011388 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011389 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011390 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011391 }
11392 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011393 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011394 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011395 type->contModel = xmlAutomataCompile(ctxt->am);
11396 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011397 xmlSchemaPCustomErr(ctxt,
11398 XML_SCHEMAP_INTERNAL,
11399 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011400 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011401 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011402 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011403 XML_SCHEMAP_NOT_DETERMINISTIC,
11404 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011405 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011406 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011407 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011408#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011409 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011410 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011411 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011412#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011413 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011414 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011415 xmlFreeAutomata(ctxt->am);
11416 ctxt->am = NULL;
11417}
11418
11419/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011420 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011421 * @elem: the schema element context
11422 * @ctxt: the schema parser context
11423 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011424 * Resolves the references of an element declaration
11425 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011426 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011427 */
11428static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011429xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011430 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011431 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011432 const xmlChar * context ATTRIBUTE_UNUSED,
11433 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011434{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011435 if ((ctxt == NULL) || (elemDecl == NULL) ||
11436 ((elemDecl != NULL) &&
11437 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011438 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011439 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011440
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011441 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011442 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011443
11444 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011445 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011446 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011447 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011448 elemDecl->namedTypeNs);
11449 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011450 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011451 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011452 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011453 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011454 XML_SCHEMA_TYPE_BASIC, "type definition");
11455 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011456 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011457 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011458 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011459 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011460
Daniel Veillardc0826a72004-08-10 14:17:33 +000011461 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011462 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011463 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011464 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011465 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11466 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011467 if (substHead == NULL) {
11468 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011469 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011470 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011471 "substitutionGroup", elemDecl->substGroup,
11472 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011473 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011474 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011475 /*
11476 * Set the "substitution group affiliation".
11477 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011478 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011479 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011480 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011481 * (type definition)...otherwise the {type definition} of the
11482 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011483 * the substitutionGroup [attribute], if present
11484 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011485 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011486 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011487 }
11488 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011489 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11490 (elemDecl->substGroup == NULL))
11491 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011492}
11493
11494/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011495 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011496 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011497 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011498 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011499 * Checks and builds the "member type definitions" property of the union
11500 * simple type. This handles part (1), part (2) is done in
11501 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11502 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011503 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011504 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011505static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011506xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11507 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011508{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011509
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011510 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011511 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011512
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011513 /*
11514 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11515 * define the explicit members as the type definitions ·resolved·
11516 * to by the items in the ·actual value· of the memberTypes [attribute],
11517 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011518 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011519 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011520 /*
11521 * Resolve references.
11522 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011523 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011524 lastLink = NULL;
11525 while (link != NULL) {
11526 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011527
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011528 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11529 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11530
11531 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11532 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11533 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011534 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011535 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11536 /*
11537 * Remove the member type link.
11538 */
11539 if (lastLink == NULL)
11540 type->memberTypes = link->next;
11541 else
11542 lastLink->next = link->next;
11543 newLink = link;
11544 link = link->next;
11545 xmlFree(newLink);
11546 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011547 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011548 lastLink = link;
11549 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011550 }
11551 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011552 /*
11553 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011554 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011555 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011556 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011557 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11558 if (link == NULL) {
11559 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11560 return (-1);
11561 }
11562 link->type = memberType;
11563 link->next = NULL;
11564 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011565 type->memberTypes = link;
11566 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011567 lastLink->next = link;
11568 lastLink = link;
11569 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011570 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011571 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011572}
11573
Daniel Veillard4255d502002-04-16 15:50:10 +000011574/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011575 * xmlSchemaIsDerivedFromBuiltInType:
11576 * @ctxt: the schema parser context
11577 * @type: the type definition
11578 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011579 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011580 *
11581 * Returns 1 if the type has the given value type, or
11582 * is derived from such a type.
11583 */
William M. Brack803812b2004-06-03 02:11:24 +000011584static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011585xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011586{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011587 if (type == NULL)
11588 return (0);
11589 if (IS_COMPLEX_TYPE(type))
11590 return (0);
11591 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11592 if (type->builtInType == valType)
11593 return(1);
11594 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11595 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11596 return (0);
11597 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11598 } else
11599 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011600
11601 return (0);
11602}
11603
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011604#if 0
11605/**
11606 * xmlSchemaIsDerivedFromBuiltInType:
11607 * @ctxt: the schema parser context
11608 * @type: the type definition
11609 * @valType: the value type
11610 *
11611 *
11612 * Returns 1 if the type has the given value type, or
11613 * is derived from such a type.
11614 */
11615static int
11616xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11617{
11618 if (type == NULL)
11619 return (0);
11620 if (IS_COMPLEX_TYPE(type))
11621 return (0);
11622 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11623 if (type->builtInType == valType)
11624 return(1);
11625 return (0);
11626 } else
11627 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11628
11629 return (0);
11630}
11631#endif
11632
11633static xmlSchemaTypePtr
11634xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11635{
11636 if (type == NULL)
11637 return (NULL);
11638 if (IS_COMPLEX_TYPE(type))
11639 return (NULL);
11640 if (type->type == XML_SCHEMA_TYPE_BASIC)
11641 return(type);
11642 else
11643 return(xmlSchemaQueryBuiltInType(type->subtypes));
11644
11645 return (NULL);
11646}
11647
Daniel Veillard3646d642004-06-02 19:19:14 +000011648/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011649 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011650 * @type: the simpleType definition
11651 *
11652 * Returns the primitive type of the given type or
11653 * NULL in case of error.
11654 */
11655static xmlSchemaTypePtr
11656xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11657{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011658
Daniel Veillard01fa6152004-06-29 17:04:39 +000011659 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011660 /*
11661 * Note that anySimpleType is actually not a primitive type
11662 * but we need that here.
11663 */
11664 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11665 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011666 return (type);
11667 type = type->baseType;
11668 }
11669
11670 return (NULL);
11671}
11672
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011673#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011674/**
11675 * xmlSchemaGetBuiltInTypeAncestor:
11676 * @type: the simpleType definition
11677 *
11678 * Returns the primitive type of the given type or
11679 * NULL in case of error.
11680 */
11681static xmlSchemaTypePtr
11682xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11683{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011684 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011685 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011686 while (type != NULL) {
11687 if (type->type == XML_SCHEMA_TYPE_BASIC)
11688 return (type);
11689 type = type->baseType;
11690 }
11691
11692 return (NULL);
11693}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011694#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011695
Daniel Veillard01fa6152004-06-29 17:04:39 +000011696/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011697 * xmlSchemaBuildAttributeUsesOwned:
11698 * @ctxt: the schema parser context
11699 * @type: the complex type definition
11700 * @cur: the attribute declaration list
11701 * @lastUse: the top of the attribute use list
11702 *
11703 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011704 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011705 * xmlSchemaBuildAttributeValidation only.
11706 */
11707static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011708xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011709 xmlSchemaAttributePtr cur,
11710 xmlSchemaAttributeLinkPtr *uses,
11711 xmlSchemaAttributeLinkPtr *lastUse)
11712{
11713 xmlSchemaAttributeLinkPtr tmp;
11714 while (cur != NULL) {
11715 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011716 /*
11717 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11718 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011719 * <attributeGroup> [children], if any."
11720 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011721 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11722 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011723 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011724 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011725 }
11726 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011727 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011728 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011729 */
11730 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011731 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11732 if (tmp == NULL) {
11733 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11734 return (-1);
11735 }
11736 tmp->attr = cur;
11737 tmp->next = NULL;
11738 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011739 *uses = tmp;
11740 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011741 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011742 *lastUse = tmp;
11743 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011744 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011745 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011746 return (0);
11747}
11748
Daniel Veillard50355f02004-06-08 17:52:16 +000011749/**
11750 * xmlSchemaCloneWildcardNsConstraints:
11751 * @ctxt: the schema parser context
11752 * @dest: the destination wildcard
11753 * @source: the source wildcard
11754 *
11755 * Clones the namespace constraints of source
11756 * and assignes them to dest.
11757 * Returns -1 on internal error, 0 otherwise.
11758 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011759static int
11760xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11761 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011762 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011763{
11764 xmlSchemaWildcardNsPtr cur, tmp, last;
11765
11766 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011767 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011768 (*dest)->any = source->any;
11769 cur = source->nsSet;
11770 last = NULL;
11771 while (cur != NULL) {
11772 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11773 if (tmp == NULL)
11774 return(-1);
11775 tmp->value = cur->value;
11776 if (last == NULL)
11777 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011778 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011779 last->next = tmp;
11780 last = tmp;
11781 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011782 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011783 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011784 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011785 if (source->negNsSet != NULL) {
11786 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11787 if ((*dest)->negNsSet == NULL)
11788 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011789 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011790 } else
11791 (*dest)->negNsSet = NULL;
11792 return(0);
11793}
11794
Daniel Veillard50355f02004-06-08 17:52:16 +000011795/**
11796 * xmlSchemaUnionWildcards:
11797 * @ctxt: the schema parser context
11798 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011799 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011800 *
11801 * Unions the namespace constraints of the given wildcards.
11802 * @completeWild will hold the resulting union.
11803 * Returns a positive error code on failure, -1 in case of an
11804 * internal error, 0 otherwise.
11805 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011806static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011807xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011808 xmlSchemaWildcardPtr completeWild,
11809 xmlSchemaWildcardPtr curWild)
11810{
11811 xmlSchemaWildcardNsPtr cur, curB, tmp;
11812
11813 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011814 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011815 * value.
11816 */
11817 if ((completeWild->any == curWild->any) &&
11818 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11819 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011820
Daniel Veillard3646d642004-06-02 19:19:14 +000011821 if ((completeWild->negNsSet == NULL) ||
11822 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011823
Daniel Veillard3646d642004-06-02 19:19:14 +000011824 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011825 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011826
11827 /*
11828 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011829 */
11830 cur = completeWild->nsSet;
11831 while (cur != NULL) {
11832 found = 0;
11833 curB = curWild->nsSet;
11834 while (curB != NULL) {
11835 if (cur->value == curB->value) {
11836 found = 1;
11837 break;
11838 }
11839 curB = curB->next;
11840 }
11841 if (!found)
11842 break;
11843 cur = cur->next;
11844 }
11845 if (found)
11846 return(0);
11847 } else
11848 return(0);
11849 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011850 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011851 /*
11852 * 2 If either O1 or O2 is any, then any must be the value
11853 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011854 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011855 if (completeWild->any == 0) {
11856 completeWild->any = 1;
11857 if (completeWild->nsSet != NULL) {
11858 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11859 completeWild->nsSet = NULL;
11860 }
11861 if (completeWild->negNsSet != NULL) {
11862 xmlFree(completeWild->negNsSet);
11863 completeWild->negNsSet = NULL;
11864 }
11865 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011866 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011867 }
11868 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011869 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011870 * then the union of those sets must be the value.
11871 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011872 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011873 int found;
11874 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011875
Daniel Veillard3646d642004-06-02 19:19:14 +000011876 cur = curWild->nsSet;
11877 start = completeWild->nsSet;
11878 while (cur != NULL) {
11879 found = 0;
11880 curB = start;
11881 while (curB != NULL) {
11882 if (cur->value == curB->value) {
11883 found = 1;
11884 break;
11885 }
11886 curB = curB->next;
11887 }
11888 if (!found) {
11889 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011890 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011891 return (-1);
11892 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011893 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011894 completeWild->nsSet = tmp;
11895 }
11896 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011897 }
11898
Daniel Veillard3646d642004-06-02 19:19:14 +000011899 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011900 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011901 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011902 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011903 * or ·absent·), then a pair of not and ·absent· must be the value.
11904 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011905 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011906 (curWild->negNsSet != NULL) &&
11907 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11908 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011909
11910 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011911 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011912 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011913 * 5.
11914 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011915 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011916 (completeWild->negNsSet->value != NULL) &&
11917 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011918 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011919 (curWild->negNsSet->value != NULL) &&
11920 (completeWild->nsSet != NULL))) {
11921
11922 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011923
Daniel Veillard3646d642004-06-02 19:19:14 +000011924 if (completeWild->nsSet != NULL) {
11925 cur = completeWild->nsSet;
11926 curB = curWild->negNsSet;
11927 } else {
11928 cur = curWild->nsSet;
11929 curB = completeWild->negNsSet;
11930 }
11931 nsFound = 0;
11932 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011933 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011934 absentFound = 1;
11935 else if (cur->value == curB->value)
11936 nsFound = 1;
11937 if (nsFound && absentFound)
11938 break;
11939 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011940 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011941
11942 if (nsFound && absentFound) {
11943 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011944 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011945 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011946 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011947 completeWild->any = 1;
11948 if (completeWild->nsSet != NULL) {
11949 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11950 completeWild->nsSet = NULL;
11951 }
11952 if (completeWild->negNsSet != NULL) {
11953 xmlFree(completeWild->negNsSet);
11954 completeWild->negNsSet = NULL;
11955 }
11956 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011957 /*
11958 * 5.2 If the set S includes the negated namespace name
11959 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000011960 * be the value.
11961 */
11962 if (completeWild->nsSet != NULL) {
11963 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11964 completeWild->nsSet = NULL;
11965 }
11966 if (completeWild->negNsSet == NULL) {
11967 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11968 if (completeWild->negNsSet == NULL)
11969 return (-1);
11970 }
11971 completeWild->negNsSet->value = NULL;
11972 } else if ((!nsFound) && absentFound) {
11973 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011974 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000011975 * namespace name, then the union is not expressible.
11976 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011977 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000011978 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011979 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011980 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011981 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011982 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011983 /*
11984 * 5.4 If the set S does not include either the negated namespace
11985 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000011986 * and a namespace name must be the value.
11987 */
11988 if (completeWild->negNsSet == NULL) {
11989 if (completeWild->nsSet != NULL) {
11990 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11991 completeWild->nsSet = NULL;
11992 }
11993 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11994 if (completeWild->negNsSet == NULL)
11995 return (-1);
11996 completeWild->negNsSet->value = curWild->negNsSet->value;
11997 }
11998 }
11999 return (0);
12000 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012001 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012002 * 6.
12003 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012004 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012005 (completeWild->negNsSet->value == NULL) &&
12006 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012007 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012008 (curWild->negNsSet->value == NULL) &&
12009 (completeWild->nsSet != NULL))) {
12010
12011 if (completeWild->nsSet != NULL) {
12012 cur = completeWild->nsSet;
12013 } else {
12014 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012015 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012016 while (cur != NULL) {
12017 if (cur->value == NULL) {
12018 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012019 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012020 * value.
12021 */
12022 completeWild->any = 1;
12023 if (completeWild->nsSet != NULL) {
12024 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12025 completeWild->nsSet = NULL;
12026 }
12027 if (completeWild->negNsSet != NULL) {
12028 xmlFree(completeWild->negNsSet);
12029 completeWild->negNsSet = NULL;
12030 }
12031 return (0);
12032 }
12033 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012034 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012035 if (completeWild->negNsSet == NULL) {
12036 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012037 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012038 * and ·absent· must be the value.
12039 */
12040 if (completeWild->nsSet != NULL) {
12041 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12042 completeWild->nsSet = NULL;
12043 }
12044 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12045 if (completeWild->negNsSet == NULL)
12046 return (-1);
12047 completeWild->negNsSet->value = NULL;
12048 }
12049 return (0);
12050 }
12051 return (0);
12052
12053}
12054
Daniel Veillard50355f02004-06-08 17:52:16 +000012055/**
12056 * xmlSchemaIntersectWildcards:
12057 * @ctxt: the schema parser context
12058 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012059 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012060 *
12061 * Intersects the namespace constraints of the given wildcards.
12062 * @completeWild will hold the resulting intersection.
12063 * Returns a positive error code on failure, -1 in case of an
12064 * internal error, 0 otherwise.
12065 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012066static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012067xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012068 xmlSchemaWildcardPtr completeWild,
12069 xmlSchemaWildcardPtr curWild)
12070{
William M. Brack803812b2004-06-03 02:11:24 +000012071 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012072
12073 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012074 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012075 * value.
12076 */
12077 if ((completeWild->any == curWild->any) &&
12078 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12079 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012080
Daniel Veillard3646d642004-06-02 19:19:14 +000012081 if ((completeWild->negNsSet == NULL) ||
12082 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012083
Daniel Veillard3646d642004-06-02 19:19:14 +000012084 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012085 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012086
12087 /*
12088 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012089 */
12090 cur = completeWild->nsSet;
12091 while (cur != NULL) {
12092 found = 0;
12093 curB = curWild->nsSet;
12094 while (curB != NULL) {
12095 if (cur->value == curB->value) {
12096 found = 1;
12097 break;
12098 }
12099 curB = curB->next;
12100 }
12101 if (!found)
12102 break;
12103 cur = cur->next;
12104 }
12105 if (found)
12106 return(0);
12107 } else
12108 return(0);
12109 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012110 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012111 /*
12112 * 2 If either O1 or O2 is any, then the other must be the value.
12113 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012114 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012115 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012116 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012117 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012118 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012119 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012120 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12121 * name or ·absent·) and the other is a set of (namespace names or
12122 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012123 * the set, minus ·absent· if it was in the set, must be the value.
12124 */
12125 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12126 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12127 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012128
Daniel Veillard3646d642004-06-02 19:19:14 +000012129 if (completeWild->nsSet == NULL) {
12130 neg = completeWild->negNsSet->value;
12131 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12132 return(-1);
12133 } else
12134 neg = curWild->negNsSet->value;
12135 /*
12136 * Remove absent and negated.
12137 */
12138 prev = NULL;
12139 cur = completeWild->nsSet;
12140 while (cur != NULL) {
12141 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012142 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012143 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012144 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012145 prev->next = cur->next;
12146 xmlFree(cur);
12147 break;
12148 }
12149 prev = cur;
12150 cur = cur->next;
12151 }
12152 if (neg != NULL) {
12153 prev = NULL;
12154 cur = completeWild->nsSet;
12155 while (cur != NULL) {
12156 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012157 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012158 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012160 prev->next = cur->next;
12161 xmlFree(cur);
12162 break;
12163 }
12164 prev = cur;
12165 cur = cur->next;
12166 }
12167 }
12168
12169 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012170 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012171 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012172 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012173 * then the intersection of those sets must be the value.
12174 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012175 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012176 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012177
Daniel Veillard3646d642004-06-02 19:19:14 +000012178 cur = completeWild->nsSet;
12179 prev = NULL;
12180 while (cur != NULL) {
12181 found = 0;
12182 curB = curWild->nsSet;
12183 while (curB != NULL) {
12184 if (cur->value == curB->value) {
12185 found = 1;
12186 break;
12187 }
12188 curB = curB->next;
12189 }
12190 if (!found) {
12191 if (prev == NULL)
12192 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012193 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012194 prev->next = cur->next;
12195 tmp = cur->next;
12196 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012197 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012198 continue;
12199 }
12200 prev = cur;
12201 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012202 }
12203
Daniel Veillard3646d642004-06-02 19:19:14 +000012204 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012205 }
12206 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012207 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012208 */
12209 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012210 (curWild->negNsSet != NULL) &&
12211 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012212 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012213 (curWild->negNsSet->value != NULL)) {
12214
12215 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012216 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012217 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012218 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012219 }
12220 /*
12221 * 6 If the one is a negation of a namespace name and the other
12222 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012223 * of a namespace name must be the value.
12224 */
12225 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12226 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012227 (completeWild->negNsSet->value == NULL)) {
12228 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012229 }
12230 return(0);
12231}
12232
Daniel Veillard50355f02004-06-08 17:52:16 +000012233/**
12234 * xmlSchemaIsWildcardNsConstraintSubset:
12235 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012236 * @sub: the first wildcard
12237 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012238 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012239 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12240 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012241 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012242 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012243 */
12244static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012245xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12246 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012247{
Daniel Veillard50355f02004-06-08 17:52:16 +000012248 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012249 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012250 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012251 if (super->any)
12252 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012253 /*
12254 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12255 * 2.2 super must be a pair of not and the same value.
12256 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012257 if ((sub->negNsSet != NULL) &&
12258 (super->negNsSet != NULL) &&
12259 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012260 return (0);
12261 /*
12262 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012263 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012264 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012265 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012266 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012267 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012268 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012269 xmlSchemaWildcardNsPtr cur, curB;
12270 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012271
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012272 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012273 while (cur != NULL) {
12274 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012275 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012276 while (curB != NULL) {
12277 if (cur->value == curB->value) {
12278 found = 1;
12279 break;
12280 }
12281 curB = curB->next;
12282 }
12283 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012284 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012285 cur = cur->next;
12286 }
12287 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012288 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012289 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012290 xmlSchemaWildcardNsPtr cur;
12291 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012292 * 3.2.2 super must be a pair of not and a namespace name or
12293 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012294 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012295 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012296 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012297 if (cur->value == super->negNsSet->value)
12298 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012299 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012300 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012301 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012302 }
12303 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012304 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012305}
12306
12307/**
12308 * xmlSchemaBuildCompleteAttributeWildcard:
12309 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012310 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012311 * @completeWild: the resulting complete wildcard
12312 *
12313 * Returns -1 in case of an internal error, 0 otherwise.
12314 */
12315static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012316xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012317 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012318 xmlSchemaWildcardPtr *completeWild)
12319{
Daniel Veillard3646d642004-06-02 19:19:14 +000012320 while (attrs != NULL) {
12321 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12322 xmlSchemaAttributeGroupPtr group;
12323
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012324 group = (xmlSchemaAttributeGroupPtr) attrs;
12325 /*
12326 * Handle attribute group references.
12327 */
12328 if (group->ref != NULL) {
12329 if (group->refItem == NULL) {
12330 /*
12331 * TODO: Should we raise a warning here?
12332 */
12333 /*
12334 * The referenced attribute group definition could not
12335 * be resolved beforehand, so skip.
12336 */
12337 attrs = attrs->next;
12338 continue;
12339 } else
12340 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012341 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012342 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012343 * For every attribute group definition, an intersected wildcard
12344 * will be created (assumed that a wildcard exists on the
12345 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012346 * at all).
12347 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12348 * that the intersection will be performed only once.
12349 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012350 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12351 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012352 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012353 group->attributes, &group->attributeWildcard) == -1)
12354 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012355 }
12356 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012357 }
12358 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012359 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012360 /*
12361 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012362 *
12363 * Although the complete wildcard might not correspond to any
12364 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012365 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012366 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12367 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12368 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012369 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012370 completeWild, group->attributeWildcard) == -1)
12371 return (-1);
12372 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012373 (*completeWild)->node = group->attributeWildcard->node;
12374 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012375 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012376 }
12377 }
12378 attrs = attrs->next;
12379 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012380
12381 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012382}
12383
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012384static int
12385xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12386 int *fixed,
12387 const xmlChar **value,
12388 xmlSchemaValPtr *val)
12389{
12390 *fixed = 0;
12391 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012392 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012393 *val = NULL;
12394
12395 if (item->defValue == NULL)
12396 item = item->refDecl;
12397
12398 if (item == NULL)
12399 return (0);
12400
12401 if (item->defValue != NULL) {
12402 *value = item->defValue;
12403 if (val != 0)
12404 *val = item->defVal;
12405 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12406 *fixed = 1;
12407 return (1);
12408 }
12409 return (0);
12410}
Daniel Veillard3646d642004-06-02 19:19:14 +000012411/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012412 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012413 * @wild: the wildcard
12414 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012415 *
12416 * Validation Rule: Wildcard allows Namespace Name
12417 * (cvc-wildcard-namespace)
12418 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012419 *
12420 * Returns 1 if the given namespace matches the wildcard,
12421 * 0 otherwise.
12422 */
12423static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012424xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12425 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012426{
12427 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012428 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012429
12430 if (wild->any)
12431 return(1);
12432 else if (wild->nsSet != NULL) {
12433 xmlSchemaWildcardNsPtr cur;
12434
12435 cur = wild->nsSet;
12436 while (cur != NULL) {
12437 if (xmlStrEqual(cur->value, ns))
12438 return(1);
12439 cur = cur->next;
12440 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012441 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012442 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012443 return(1);
12444
Daniel Veillard3646d642004-06-02 19:19:14 +000012445 return(0);
12446}
12447
12448/**
12449 * xmlSchemaBuildAttributeValidation:
12450 * @ctxt: the schema parser context
12451 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012452 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012453 *
12454 * Builds the wildcard and the attribute uses on the given complex type.
12455 * Returns -1 if an internal error occurs, 0 otherwise.
12456 */
12457static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012458xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12459 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012460{
12461 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012462 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12463 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012464 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012465 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012466 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012467 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012468
Daniel Veillard01fa6152004-06-29 17:04:39 +000012469 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012470 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012471 * Complex Type Definition with complex content Schema Component.
12472 *
12473 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012474 * TODO: Add checks for absent referenced attribute declarations and
12475 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012476 */
12477 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012478 PERROR_INT("xmlSchemaBuildAttributeValidation",
12479 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012480 return (-1);
12481 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012482 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012483 PERROR_INT("xmlSchemaBuildAttributeValidation",
12484 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012485 return (-1);
12486 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012487 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012488 /*
12489 * Inherit the attribute uses of the base type.
12490 */
12491 /*
12492 * NOTE: It is allowed to "extend" the anyType complex type.
12493 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012494 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012495 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012496 for (cur = baseType->attributeUses; cur != NULL;
12497 cur = cur->next) {
12498 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012499 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12500 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012501 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012502 "building attribute uses of complexType", NULL);
12503 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012504 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012505 tmp->attr = cur->attr;
12506 tmp->next = NULL;
12507 if (type->attributeUses == NULL) {
12508 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012509 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012510 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012511 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012512 }
12513 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012514 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012515 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012516 /*
12517 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012518 */
12519 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12520 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012521 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012522 * NOTE: During the parse time, the wildcard is created on the complexType
12523 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012524 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012525 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012526 PERROR_INT("xmlSchemaBuildAttributeValidation",
12527 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012528 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012529 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012530
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012531 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12532 ((IS_ANYTYPE(baseType)) ||
12533 ((baseType != NULL) &&
12534 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12535 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012536 if (type->attributeWildcard != NULL) {
12537 /*
12538 * Union the complete wildcard with the base wildcard.
12539 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012540 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012541 baseType->attributeWildcard) == -1)
12542 return (-1);
12543 } else {
12544 /*
12545 * Just inherit the wildcard.
12546 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012547 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012548 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012549 * wildcard is shared.
12550 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012551 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012552 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012553 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012554
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012555 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12556 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012557 /*
12558 * Derivation Valid (Restriction, Complex)
12559 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012560 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012561 if (baseType->attributeWildcard == NULL) {
12562 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012563 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012564 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012565 "The type has an attribute wildcard, "
12566 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012567 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012568 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012569 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012570 } else if (xmlSchemaCheckCOSNSSubset(
12571 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012572 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012573 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012574 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012575 NULL, type, NULL,
12576 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012577 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012578 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12579 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012580 return (1);
12581 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012582 /* 4.3 Unless the {base type definition} is the ·ur-type
12583 * definition·, the complex type definition's {attribute
12584 * wildcard}'s {process contents} must be identical to or
12585 * stronger than the {base type definition}'s {attribute
12586 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012587 * than lax is stronger than skip.
12588 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012589 if ((! IS_ANYTYPE(baseType)) &&
12590 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012591 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012592 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012593 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012594 NULL, type, NULL,
12595 "The 'process contents' of the attribute wildcard is "
12596 "weaker than the one in the base type %s",
12597 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012598 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012599 return (1);
12600 }
12601 }
12602 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12603 /*
12604 * Derivation Valid (Extension)
12605 * At this point the type and the base have both, either
12606 * no wildcard or a wildcard.
12607 */
12608 if ((baseType->attributeWildcard != NULL) &&
12609 (baseType->attributeWildcard != type->attributeWildcard)) {
12610 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012611 if (xmlSchemaCheckCOSNSSubset(
12612 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012613 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012614 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012615 NULL, type, NULL,
12616 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012617 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012618 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12619 FREE_AND_NULL(str)
12620 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012621 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012622 }
12623 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012624
Daniel Veillard3646d642004-06-02 19:19:14 +000012625 /*
12626 * Gather attribute uses defined by this type.
12627 */
12628 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012629 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012630 &uses, &lastUse) == -1) {
12631 return (-1);
12632 }
12633 }
12634 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012635 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012636 * not have identical {name}s and {target namespace}s."
12637 *
12638 * For "extension" this is done further down.
12639 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012640 if ((uses != NULL) && ((type->flags &
12641 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012642 cur = uses;
12643 while (cur != NULL) {
12644 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012645 while (tmp != NULL) {
12646 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012647 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012648 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012649 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12650
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012651 xmlSchemaPAttrUseErr(pctxt,
12652 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12653 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012654 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012655 xmlSchemaFormatQName(&str,
12656 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12657 xmlSchemaGetAttrName(tmp->attr)));
12658 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012659 break;
12660 }
12661 tmp = tmp->next;
12662 }
12663 cur = cur->next;
12664 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012665 }
12666 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012667 /*
12668 * Derive by restriction.
12669 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012670 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012671 type->attributeUses = uses;
12672 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012673 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012674 const xmlChar *bEffValue;
12675 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012676
12677 cur = uses;
12678 while (cur != NULL) {
12679 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012680 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012681 base = type->attributeUses;
12682 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012683 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012684 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012685 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012686 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012687
12688 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012689
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012690 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012691 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12692 (base->attr->occurs ==
12693 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12694 /*
12695 * NOOP.
12696 */
12697 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012698 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12699 (base->attr->occurs ==
12700 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012701 /*
12702 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012703 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012704 xmlSchemaPAttrUseErr(pctxt,
12705 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12706 type, cur->attr,
12707 "The 'optional' use is inconsistent with a "
12708 "matching 'required' use of the base type",
12709 NULL);
12710 } else if ((cur->attr->occurs ==
12711 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12712 (base->attr->occurs ==
12713 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12714 /*
12715 * derivation-ok-restriction 3
12716 */
12717 xmlSchemaPCustomErr(pctxt,
12718 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12719 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012720 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012721 "attribute use '%s' of the base type is "
12722 "missing",
12723 xmlSchemaFormatQName(&str,
12724 xmlSchemaGetAttrTargetNsURI(base->attr),
12725 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012726 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012727 } else if (xmlSchemaCheckCOSSTDerivedOK(
12728 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12729
12730 /*
12731 * SPEC (2.1.2) "R's {attribute declaration}'s
12732 * {type definition} must be validly derived from
12733 * B's {type definition} given the empty set as
12734 * defined in Type Derivation OK (Simple) (§3.14.6)."
12735 */
12736 xmlSchemaPAttrUseErr(pctxt,
12737 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12738 type, cur->attr,
12739 "The attribute declaration's type "
12740 "definition is not validly derived from "
12741 "the corresponding definition in the "
12742 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012743 } else {
12744 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012745 * 2.1.3 [Definition:] Let the effective value
12746 * constraint of an attribute use be its {value
12747 * constraint}, if present, otherwise its {attribute
12748 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012749 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012750 xmlSchemaGetEffectiveValueConstraint(base->attr,
12751 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012752 /*
12753 * 2.1.3 ... one of the following must be true
12754 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012755 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012756 * ·absent· or default.
12757 */
12758 if ((bEffValue != NULL) &&
12759 (effFixed == 1)) {
12760 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012761
12762 xmlSchemaGetEffectiveValueConstraint(base->attr,
12763 &effFixed, &rEffValue, 0);
12764 /*
12765 * 2.1.3.2 R's ·effective value constraint· is
12766 * fixed with the same string as B's.
12767 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012768 */
12769 if ((effFixed == 0) ||
12770 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012771 xmlSchemaPAttrUseErr(pctxt,
12772 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12773 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012774 "The effective value constraint of the "
12775 "attribute use is inconsistent with "
12776 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012777 NULL);
12778 } else {
12779 /*
12780 * Override the attribute use.
12781 */
12782 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012783 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012784 } else
12785 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012786 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012787
Daniel Veillard3646d642004-06-02 19:19:14 +000012788 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012789 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012790 base = base->next;
12791 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012792
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012793 if ((!found) && (cur->attr->occurs !=
12794 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12795 /*
12796 * derivation-ok-restriction 2.2
12797 */
12798 if ((baseType->attributeWildcard == NULL) ||
12799 (xmlSchemaCheckCVCWildcardNamespace(
12800 baseType->attributeWildcard,
12801 cur->attr->targetNamespace) != 1)) {
12802 xmlSchemaPAttrUseErr(pctxt,
12803 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12804 type, cur->attr,
12805 "Neither a matching attribute use, "
12806 "nor a matching wildcard in the base type does exist",
12807 NULL);
12808 } else {
12809 /*
12810 * Add the attribute use.
12811 *
12812 * Note that this may lead to funny derivation error reports, if
12813 * multiple equal attribute uses exist; but this is not
12814 * allowed anyway, and it will be reported beforehand.
12815 */
12816 tmp = cur;
12817 if (prev != NULL)
12818 prev->next = cur->next;
12819 else
12820 uses = cur->next;
12821 cur = cur->next;
12822 tmp->next = NULL;
12823 if (type->attributeUses == NULL) {
12824 type->attributeUses = tmp;
12825 } else
12826 lastBaseUse->next = tmp;
12827 lastBaseUse = tmp;
12828
12829 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012830 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012831 }
12832 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012833 cur = cur->next;
12834 }
12835 if (uses != NULL)
12836 xmlSchemaFreeAttributeUseList(uses);
12837 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012838 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012839 /*
12840 * The spec allows only appending, and not other kinds of extensions.
12841 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012842 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012843 */
12844 if (uses != NULL) {
12845 if (type->attributeUses == NULL) {
12846 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012847 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012848 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012849 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012850 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012851 PERROR_INT("xmlSchemaBuildAttributeValidation",
12852 "no derivation method");
12853 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012854 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012855 /*
12856 * 3.4.6 -> Complex Type Definition Properties Correct
12857 */
12858 if (type->attributeUses != NULL) {
12859 cur = type->attributeUses;
12860 prev = NULL;
12861 while (cur != NULL) {
12862 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012863 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012864 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012865 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012866 * Note that this was already done for "restriction" and types derived from
12867 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012868 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012869 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12870 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012871 while (tmp != NULL) {
12872 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012873 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012874 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012875 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012876
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012877 xmlSchemaPAttrUseErr(pctxt,
12878 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12879 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012880 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012881 break;
12882 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012883 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012884 }
12885 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012886 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012887 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012888 * not have {type definition}s which are or are derived from ID.
12889 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012890 if ((cur->attr->subtypes != NULL) &&
12891 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12892 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012893 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012894 xmlSchemaPAttrUseErr(pctxt,
12895 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12896 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012897 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012898 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012899 NULL);
12900 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012901 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012902 id = cur;
12903 }
12904 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012905 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012906 * stage is to be able to catch dublicate attribute uses. So we had to keep
12907 * prohibited uses in the list as well.
12908 */
12909 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12910 tmp = cur;
12911 if (prev == NULL)
12912 type->attributeUses = cur->next;
12913 else
12914 prev->next = cur->next;
12915 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012916 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012917 } else {
12918 prev = cur;
12919 cur = cur->next;
12920 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012921 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012922 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012923 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012924 * TODO: This check should be removed if we are 100% sure of
12925 * the base type attribute uses already being built.
12926 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012927 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012928 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012929 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012930 PERROR_INT("xmlSchemaBuildAttributeValidation",
12931 "attribute uses not builded on base type");
12932 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012933 return (0);
12934}
12935
12936/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012937 * xmlSchemaTypeFinalContains:
12938 * @schema: the schema
12939 * @type: the type definition
12940 * @final: the final
12941 *
12942 * Evaluates if a type definition contains the given "final".
12943 * This does take "finalDefault" into account as well.
12944 *
12945 * Returns 1 if the type does containt the given "final",
12946 * 0 otherwise.
12947 */
12948static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012949xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012950{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012951 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012952 return (0);
12953 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012954 return (1);
12955 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012956 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012957}
12958
12959/**
12960 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12961 * @type: the Union Simple Type
12962 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012963 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012964 * returns NULL otherwise.
12965 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012966static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012967xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12968{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012969 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012970 if (type->memberTypes != NULL)
12971 return (type->memberTypes);
12972 else
12973 type = type->baseType;
12974 }
12975 return (NULL);
12976}
12977
12978/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012979 * xmlSchemaGetParticleTotalRangeMin:
12980 * @particle: the particle
12981 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012982 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012983 * (all and sequence) + (choice)
12984 *
12985 * Returns the minimun Effective Total Range.
12986 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012987static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012988xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012989{
12990 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012991 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012992 return (0);
12993 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012994 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012995 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012996 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012997
12998 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012999 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013000 while (part != NULL) {
13001 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13002 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013003 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013004 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013005 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013006 if (cur == 0)
13007 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013008 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013009 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013010 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013011 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013012 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013013 } else {
13014 /* <all> and <sequence> */
13015 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013016 xmlSchemaParticlePtr part =
13017 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013018
13019 if (part == NULL)
13020 return (0);
13021 do {
13022 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13023 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013024 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013025 else
13026 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013027 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013028 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013029 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013030 }
13031}
13032
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013033/**
13034 * xmlSchemaGetParticleTotalRangeMax:
13035 * @particle: the particle
13036 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013037 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013038 * (all and sequence) + (choice)
13039 *
13040 * Returns the maximum Effective Total Range.
13041 */
13042static int
13043xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13044{
13045 if ((particle->children == NULL) ||
13046 (particle->children->children == NULL))
13047 return (0);
13048 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13049 int max = -1, cur;
13050 xmlSchemaParticlePtr part =
13051 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013052
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013053 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13054 if (part->children == NULL)
13055 continue;
13056 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13057 (part->children->type == XML_SCHEMA_TYPE_ANY))
13058 cur = part->maxOccurs;
13059 else
13060 cur = xmlSchemaGetParticleTotalRangeMax(part);
13061 if (cur == UNBOUNDED)
13062 return (UNBOUNDED);
13063 if ((max < cur) || (max == -1))
13064 max = cur;
13065 }
13066 /* TODO: Handle overflows? */
13067 return (particle->maxOccurs * max);
13068 } else {
13069 /* <all> and <sequence> */
13070 int sum = 0, cur;
13071 xmlSchemaParticlePtr part =
13072 (xmlSchemaParticlePtr) particle->children->children;
13073
13074 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13075 if (part->children == NULL)
13076 continue;
13077 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13078 (part->children->type == XML_SCHEMA_TYPE_ANY))
13079 cur = part->maxOccurs;
13080 else
13081 cur = xmlSchemaGetParticleTotalRangeMax(part);
13082 if (cur == UNBOUNDED)
13083 return (UNBOUNDED);
13084 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13085 return (UNBOUNDED);
13086 sum += cur;
13087 }
13088 /* TODO: Handle overflows? */
13089 return (particle->maxOccurs * sum);
13090 }
13091}
13092
13093/**
13094 * xmlSchemaIsParticleEmptiable:
13095 * @particle: the particle
13096 *
13097 * Schema Component Constraint: Particle Emptiable
13098 * Checks whether the given particle is emptiable.
13099 *
13100 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013101 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013102static int
13103xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13104{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013105 /*
13106 * SPEC (1) "Its {min occurs} is 0."
13107 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013108 if ((particle == NULL) || (particle->minOccurs == 0) ||
13109 (particle->children == NULL))
13110 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013111 /*
13112 * SPEC (2) "Its {term} is a group and the minimum part of the
13113 * effective total range of that group, [...] is 0."
13114 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013115 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013116 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013117 return (1);
13118 }
13119 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013120}
13121
13122/**
13123 * xmlSchemaCheckCOSSTDerivedOK:
13124 * @type: the derived simple type definition
13125 * @baseType: the base type definition
13126 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013127 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013128 * Type Derivation OK (Simple) (cos-st-derived-OK)
13129 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013130 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013131 * derived from @baseType.
13132 *
13133 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013134 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013135static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013136xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13137 xmlSchemaTypePtr baseType,
13138 int subset)
13139{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013140 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013141 * 1 They are the same type definition.
13142 * TODO: The identy check might have to be more complex than this.
13143 */
13144 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013145 return (0);
13146 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013147 * 2.1 restriction is not in the subset, or in the {final}
13148 * of its own {base type definition};
13149 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013150 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013151 (xmlSchemaTypeFinalContains(type->baseType,
13152 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13153 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013154 }
13155 /* 2.2 */
13156 if (type->baseType == baseType) {
13157 /*
13158 * 2.2.1 D's ·base type definition· is B.
13159 */
13160 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013161 }
13162 /*
13163 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13164 * and is validly derived from B given the subset, as defined by this
13165 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013166 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013167 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013168 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013169 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013170 return (0);
13171 }
13172 /*
13173 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013174 * definition·.
13175 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013176 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013177 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013178 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013179 }
13180 /*
13181 * 2.2.4 B's {variety} is union and D is validly derived from a type
13182 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013183 * defined by this constraint.
13184 *
13185 * NOTE: This seems not to involve built-in types, since there is no
13186 * built-in Union Simple Type.
13187 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013188 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013189 xmlSchemaTypeLinkPtr cur;
13190
13191 cur = baseType->memberTypes;
13192 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013193 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013194 return (0);
13195 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013196 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013197 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013198
Daniel Veillard01fa6152004-06-29 17:04:39 +000013199 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13200}
13201
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013202/**
13203 * xmlSchemaCheckTypeDefCircularInternal:
13204 * @pctxt: the schema parser context
13205 * @ctxtType: the type definition
13206 * @ancestor: an ancestor of @ctxtType
13207 *
13208 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013209 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013210 *
13211 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13212 * circular, 0 otherwise.
13213 */
13214static int
13215xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13216 xmlSchemaTypePtr ctxtType,
13217 xmlSchemaTypePtr ancestor)
13218{
13219 int ret;
13220
13221 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13222 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013223
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013224 if (ctxtType == ancestor) {
13225 xmlSchemaPCustomErr(pctxt,
13226 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13227 NULL, ctxtType, GET_NODE(ctxtType),
13228 "The definition is circular", NULL);
13229 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13230 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013231 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13232 /*
13233 * Avoid inifinite recursion on circular types not yet checked.
13234 */
13235 return (0);
13236 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013237 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13238 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13239 ancestor->baseType);
13240 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13241 return (ret);
13242}
13243
13244/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013245 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013246 * @item: the complex/simple type definition
13247 * @ctxt: the parser context
13248 * @name: the name
13249 *
13250 * Checks for circular type definitions.
13251 */
13252static void
13253xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013254 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013255 const xmlChar * name ATTRIBUTE_UNUSED)
13256{
13257 if ((item == NULL) ||
13258 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13259 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13260 return;
13261 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13262
13263}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013264
13265/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013266 * xmlSchemaResolveTypeDefs:
13267 * @item: the complex/simple type definition
13268 * @ctxt: the parser context
13269 * @name: the name
13270 *
13271 * Checks for circular type definitions.
13272 */
13273static void
13274xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013275 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013276 const xmlChar * name ATTRIBUTE_UNUSED)
13277{
13278 if (typeDef == NULL)
13279 return;
13280
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013281 /*
13282 * Resolve the base type.
13283 */
13284 if (typeDef->baseType == NULL) {
13285 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13286 typeDef->base, typeDef->baseNs);
13287 if (typeDef->baseType == NULL) {
13288 xmlSchemaPResCompAttrErr(ctxt,
13289 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013290 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013291 "base", typeDef->base, typeDef->baseNs,
13292 XML_SCHEMA_TYPE_SIMPLE, NULL);
13293 return;
13294 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013295 }
13296 if (IS_SIMPLE_TYPE(typeDef)) {
13297 if (VARIETY_UNION(typeDef)) {
13298 /*
13299 * Resolve the memberTypes.
13300 */
13301 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13302 return;
13303 } else if (VARIETY_LIST(typeDef)) {
13304 /*
13305 * Resolve the itemType.
13306 */
13307 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13308 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13309 typeDef->ref, typeDef->refNs);
13310 if ((typeDef->subtypes == NULL) ||
13311 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13312 typeDef->subtypes = NULL;
13313 xmlSchemaPResCompAttrErr(ctxt,
13314 XML_SCHEMAP_SRC_RESOLVE,
13315 typeDef, typeDef->node,
13316 "itemType", typeDef->ref, typeDef->refNs,
13317 XML_SCHEMA_TYPE_SIMPLE, NULL);
13318 }
13319 }
13320 return;
13321 }
13322 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013323}
13324
13325
13326
13327/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013328 * xmlSchemaCheckSTPropsCorrect:
13329 * @ctxt: the schema parser context
13330 * @type: the simple type definition
13331 *
13332 * Checks st-props-correct.
13333 *
13334 * Returns 0 if the properties are correct,
13335 * if not, a positive error code and -1 on internal
13336 * errors.
13337 */
13338static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013339xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013340 xmlSchemaTypePtr type)
13341{
13342 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13343 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013344 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013345
Daniel Veillardc0826a72004-08-10 14:17:33 +000013346 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013347 /*
13348 * Schema Component Constraint: Simple Type Definition Properties Correct
13349 *
13350 * NOTE: This is somehow redundant, since we actually built a simple type
13351 * to have all the needed information; this acts as an self test.
13352 */
13353 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13354 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013355 /* Base type: If the datatype has been ·derived· by ·restriction·
13356 * then the Simple Type Definition component from which it is ·derived·,
13357 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013358 */
13359 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013360 /*
13361 * TODO: Think about: "modulo the impact of Missing
13362 * Sub-components (§5.3)."
13363 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013364 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013365 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013366 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013367 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013368 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013369
Daniel Veillard01fa6152004-06-29 17:04:39 +000013370 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013371 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013372 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013373 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013374 NULL, type, NULL,
13375 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013376 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013377 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013378 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13379 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013380 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13381 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13382 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013383 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013384 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013385 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013386 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013387 "the simple ur-type definition as base type, not '%s'",
13388 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013389 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013390 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13391 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013392 /*
13393 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013394 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013395 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13396 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013397 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013398 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013399 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013400 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013401 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13402 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013403 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013404
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013405 /*
13406 * 3 The {final} of the {base type definition} must not contain restriction.
13407 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013408 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013409 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13410 xmlSchemaPCustomErr(ctxt,
13411 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013412 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013413 "The 'final' of its base type '%s' must not contain "
13414 "'restriction'",
13415 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013416 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013417 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013418 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013419
13420 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013421 * 2 All simple type definitions must be derived ultimately from the ·simple
13422 * ur-type definition (so· circular definitions are disallowed). That is, it
13423 * must be possible to reach a built-in primitive datatype or the ·simple
13424 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013425 *
13426 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013428 return (0);
13429}
13430
13431/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013432 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013433 * @ctxt: the schema parser context
13434 * @type: the simple type definition
13435 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013436 * Schema Component Constraint:
13437 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13438
13439 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013440 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013441 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013442 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013443 * a positive error code otherwise.
13444 */
13445static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013446xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013447 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013448{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013449 xmlChar *str = NULL;
13450
Daniel Veillard01fa6152004-06-29 17:04:39 +000013451 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013452 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13453 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013454 return (-1);
13455 }
13456
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013457 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013458 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013459 /*
13460 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013461 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013462 */
13463 if (! VARIETY_ATOMIC(type->baseType)) {
13464 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013465 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013466 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013467 "The base type '%s' is not an atomic simple type",
13468 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013469 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013470 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13471 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013472 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013473 * restriction.
13474 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013475 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013476 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013477 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013478 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013479 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013480 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013481 "The final of its base type '%s' must not contain 'restriction'",
13482 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013483 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013484 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13485 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013486
13487 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013488 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013489 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013490 * Primitive datatypes.
13491 */
13492 if (type->facets != NULL) {
13493 xmlSchemaFacetPtr facet;
13494 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013495
Daniel Veillard01fa6152004-06-29 17:04:39 +000013496 primitive = xmlSchemaGetPrimitiveType(type);
13497 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013498 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13499 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013500 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013501 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013502 facet = type->facets;
13503 do {
13504 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013505 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013506 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013507 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013508 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013509 }
13510 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013511 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013512 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013513 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013514 }
13515 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013516 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13517 * of the {base type definition} (call this BF),then the DF's {value}
13518 * must be a valid restriction of BF's {value} as defined in
13519 * [XML Schemas: Datatypes]."
13520 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013521 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013522 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013523 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013524 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013525 xmlSchemaTypePtr itemType = NULL;
13526
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013527 itemType = type->subtypes;
13528 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013529 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13530 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013531 return (-1);
13532 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013533 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013535 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013536 * 2.1 The {item type definition} must have a {variety} of atomic or
13537 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013538 * must be atomic).
13539 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540 if ((! VARIETY_ATOMIC(itemType)) &&
13541 (! VARIETY_UNION(itemType))) {
13542 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013543 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013544 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013545 "The item type '%s' does not have a variety of atomic or union",
13546 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013547 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013548 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013549 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013550 xmlSchemaTypeLinkPtr member;
13551
13552 member = itemType->memberTypes;
13553 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013554 if (! VARIETY_ATOMIC(member->type)) {
13555 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013556 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013557 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013558 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013559 "member type '%s' of this item type is not atomic",
13560 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013561 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013562 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13563 }
13564 member = member->next;
13565 }
13566 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013567
13568 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013569 xmlSchemaFacetPtr facet;
13570 /*
13571 * This is the case if we have: <simpleType><list ..
13572 */
13573 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013574 * 2.3.1
13575 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013576 * contain list.
13577 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013578 if (xmlSchemaTypeFinalContains(itemType,
13579 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13580 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013581 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013582 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013583 "The final of its item type '%s' must not contain 'list'",
13584 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013585 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013586 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13587 }
13588 /*
13589 * 2.3.1.2 The {facets} must only contain the whiteSpace
13590 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013591 * OPTIMIZE TODO: the S4S already disallows any facet
13592 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013593 */
13594 if (type->facets != NULL) {
13595 facet = type->facets;
13596 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013597 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013598 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013599 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013600 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13602 }
13603 facet = facet->next;
13604 } while (facet != NULL);
13605 }
13606 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013607 * MAYBE TODO: (Hmm, not really) Datatypes states:
13608 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13609 * whose ·lexical space· allows space (such as string or anyURI)or
13610 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013611 * ·lexical space· allows space.
13612 */
13613 } else {
13614 /*
13615 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013616 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013617 */
13618 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013619 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013620 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13621 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013622 if (! VARIETY_LIST(type->baseType)) {
13623 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013624 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013625 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013626 "The base type '%s' must be a list type",
13627 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013628 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013629 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13630 }
13631 /*
13632 * 2.3.2.2 The {final} of the {base type definition} must not
13633 * contain restriction.
13634 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013635 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013636 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013637 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013638 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013639 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013640 "The 'final' of the base type '%s' must not contain 'restriction'",
13641 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013642 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013643 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13644 }
13645 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013646 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013647 * from the {base type definition}'s {item type definition} given
13648 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13649 */
13650 {
13651 xmlSchemaTypePtr baseItemType;
13652
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013653 baseItemType = type->baseType->subtypes;
13654 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013655 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13656 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013657 return (-1);
13658 }
13659 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013660 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13661 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013662 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013663 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013664 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013665 NULL, type, NULL,
13666 "The item type '%s' is not validly derived from "
13667 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013668 xmlSchemaGetComponentQName(&str, itemType),
13669 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13670 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013671
13672 FREE_AND_NULL(str)
13673 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013674 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013675 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13676 }
13677 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013678
Daniel Veillard01fa6152004-06-29 17:04:39 +000013679 if (type->facets != NULL) {
13680 xmlSchemaFacetPtr facet;
13681 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013682 /*
13683 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013684 * and enumeration facet components are allowed among the {facets}.
13685 */
13686 facet = type->facets;
13687 do {
13688 switch (facet->type) {
13689 case XML_SCHEMA_FACET_LENGTH:
13690 case XML_SCHEMA_FACET_MINLENGTH:
13691 case XML_SCHEMA_FACET_MAXLENGTH:
13692 case XML_SCHEMA_FACET_WHITESPACE:
13693 /*
13694 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013695 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013696 */
13697 case XML_SCHEMA_FACET_PATTERN:
13698 case XML_SCHEMA_FACET_ENUMERATION:
13699 break;
13700 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013701 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013702 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013703 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013704 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013705 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013706 * invalid facets.
13707 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013708 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013709 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013710 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013711 facet = facet->next;
13712 } while (facet != NULL);
13713 if (ok == 0)
13714 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13715 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013716 * SPEC (2.3.2.5) (same as 1.3.2)
13717 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013718 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013719 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013720 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013721 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013722 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013723 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013724 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013725 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013726 * atomic or list.
13727 */
13728 xmlSchemaTypeLinkPtr member;
13729
13730 member = type->memberTypes;
13731 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013732 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013733 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013734
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013735 if ((! VARIETY_ATOMIC(member->type)) &&
13736 (! VARIETY_LIST(member->type))) {
13737 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013738 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013739 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013740 "The member type '%s' is neither an atomic, nor a list type",
13741 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013742 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013743 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13744 }
13745 member = member->next;
13746 }
13747 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013748 * 3.3.1 If the {base type definition} is the ·simple ur-type
13749 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013750 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013751 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013752 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013753 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013754 * {final} which does not contain union.
13755 */
13756 member = type->memberTypes;
13757 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013758 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013759 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013760 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013761 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013762 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013763 "The 'final' of member type '%s' contains 'union'",
13764 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013765 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013766 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13767 }
13768 member = member->next;
13769 }
13770 /*
13771 * 3.3.1.2 The {facets} must be empty.
13772 */
13773 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013774 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013775 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013776 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013777 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013778 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13779 }
13780 } else {
13781 /*
13782 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013783 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013784 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013785 if (! VARIETY_UNION(type->baseType)) {
13786 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013788 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013789 "The base type '%s' is not a union type",
13790 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013791 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013792 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13793 }
13794 /*
13795 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13796 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013797 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013798 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013799 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013800 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013801 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013802 "The 'final' of its base type '%s' must not contain 'restriction'",
13803 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013804 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013805 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13806 }
13807 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013808 * 3.3.2.3 The {member type definitions}, in order, must be validly
13809 * derived from the corresponding type definitions in the {base
13810 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013811 * as defined in Type Derivation OK (Simple) (§3.14.6).
13812 */
13813 {
13814 xmlSchemaTypeLinkPtr baseMember;
13815
13816 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013817 * OPTIMIZE: if the type is restricting, it has no local defined
13818 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013819 * thus a check for equality can be skipped.
13820 */
13821 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013822 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013823 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013824 * types of it's base type. This check seems not necessary with
13825 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013826 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013827 */
13828 if (type->memberTypes != NULL) {
13829 member = type->memberTypes;
13830 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013831 if ((member == NULL) && (baseMember != NULL)) {
13832 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13833 "different number of member types in base");
13834 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013835 while (member != NULL) {
13836 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013837 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13838 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013839 }
13840 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013841 (xmlSchemaCheckCOSSTDerivedOK(
13842 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013843 xmlChar *strBMT = NULL, *strBT = NULL;
13844
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013845 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013846 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13847 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013848 "The member type %s is not validly "
13849 "derived from its corresponding member "
13850 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013851 xmlSchemaGetComponentQName(&str, member->type),
13852 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13853 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013854 FREE_AND_NULL(str)
13855 FREE_AND_NULL(strBMT)
13856 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013857 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013858 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013859 member = member->next;
13860 baseMember = baseMember->next;
13861 }
13862 }
13863 }
13864 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013865 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013866 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013867 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013868 if (type->facets != NULL) {
13869 xmlSchemaFacetPtr facet;
13870 int ok = 1;
13871
13872 facet = type->facets;
13873 do {
13874 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13875 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013876 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013877 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013878 NULL, type, facet);
13879 ok = 0;
13880 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013881 facet = facet->next;
13882 } while (facet != NULL);
13883 if (ok == 0)
13884 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013885
Daniel Veillard01fa6152004-06-29 17:04:39 +000013886 }
13887 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013888 * SPEC (3.3.2.5) (same as 1.3.2)
13889 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013890 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013891 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013892 */
13893 }
13894 }
13895
13896 return (0);
13897}
13898
13899/**
13900 * xmlSchemaCheckSRCSimpleType:
13901 * @ctxt: the schema parser context
13902 * @type: the simple type definition
13903 *
13904 * Checks crc-simple-type constraints.
13905 *
13906 * Returns 0 if the constraints are satisfied,
13907 * if not a positive error code and -1 on internal
13908 * errors.
13909 */
13910static int
13911xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13912 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013913{
13914 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013915 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013916 * must satisfy the conditions set out in Constraints on Simple Type
13917 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013918 */
13919 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13920 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13921 /*
13922 * TODO: Removed this, since it got annoying to get an
13923 * extra error report, if anything failed until now.
13924 * Enable this if needed.
13925 */
13926 /*
13927 xmlSchemaPErr(ctxt, type->node,
13928 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013929 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013930 "on simple type definitions.\n",
13931 type->name, NULL);
13932 */
13933 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13934 }
13935
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013936 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013937 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013938 * src-simple-type.2 If the <restriction> alternative is chosen,
13939 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013940 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013941 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013942 /*
13943 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013944 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013945 */
13946 } else if (VARIETY_LIST(type)) {
13947 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13948 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013949 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013950 *
13951 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013952 */
13953 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013954 xmlSchemaTypeLinkPtr member;
13955 xmlSchemaTypePtr ancestor, anySimpleType;
13956
13957 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13958
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013959 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13960 * the <union> alternative is chosen, there must not be any entries
13961 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000013962 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013963 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013964 member = type->memberTypes;
13965 while (member != NULL) {
13966 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013967 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013968 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013969 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013970 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013971 NULL, type, NULL,
13972 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013973 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013974 }
13975 if (IS_NOT_TYPEFIXED(ancestor))
13976 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013977 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013978 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013979 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013980 * type as item type, which in turn has a list ST as member
13981 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000013982 * was not yet performed.
13983 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013984 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013985
Daniel Veillard01fa6152004-06-29 17:04:39 +000013986 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013987 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013988 member = member->next;
13989 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013990 }
13991
13992 return (0);
13993}
13994
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013995static int
13996xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13997{
13998 if (ctxt->vctxt == NULL) {
13999 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14000 if (ctxt->vctxt == NULL) {
14001 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014002 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014003 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014004 "failed to create a temp. validation context.\n",
14005 NULL, NULL);
14006 return (-1);
14007 }
14008 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014009 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014010 }
14011 return (0);
14012}
14013
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014014static int
14015xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14016 xmlNodePtr node,
14017 xmlSchemaTypePtr type,
14018 const xmlChar *value,
14019 xmlSchemaValPtr *retVal,
14020 int fireErrors,
14021 int normalize,
14022 int isNormalized);
14023
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014024/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014025 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014026 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014027 * @type: the simple type definition
14028 * @value: the default value
14029 * @node: an optional node (the holder of the value)
14030 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014031 * Schema Component Constraint: Element Default Valid (Immediate)
14032 * (cos-valid-default)
14033 * This will be used by the parser only. For the validator there's
14034 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014035 *
14036 * Returns 0 if the constraints are satisfied,
14037 * if not, a positive error code and -1 on internal
14038 * errors.
14039 */
14040static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014041xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14042 xmlNodePtr node,
14043 xmlSchemaTypePtr type,
14044 const xmlChar *value,
14045 xmlSchemaValPtr *val)
14046{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014047 int ret = 0;
14048
14049 /*
14050 * cos-valid-default:
14051 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014052 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014053 * definition the appropriate case among the following must be true:
14054 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014055 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014056 /*
14057 * Complex type.
14058 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014059 * SPEC (2.1) "its {content type} must be a simple type definition
14060 * or mixed."
14061 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014062 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014063 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014064 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014065 if ((! HAS_SIMPLE_CONTENT(type)) &&
14066 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14067 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014068 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014069 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014070 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014071 "For a string to be a valid default, the type definition "
14072 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014073 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014074 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14075 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014076 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014077 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014078 * 1 If the type definition is a simple type definition, then the string
14079 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014080 * Valid (§3.14.4).
14081 *
14082 * AND
14083 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014084 * 2.2.1 If the {content type} is a simple type definition, then the
14085 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014086 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014087 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014088 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014089 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14090 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014091 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014092 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14093 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014094 else
14095 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014096
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014097 if (ret < 0) {
14098 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14099 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014100 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014101
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014102 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014103}
14104
14105/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014106 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014107 * @ctxt: the schema parser context
14108 * @type: the complex type definition
14109 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014110 *.(4.6) Constraints on Complex Type Definition Schema Components
14111 * Schema Component Constraint:
14112 * Complex Type Definition Properties Correct (ct-props-correct)
14113 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014114 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014115 * Returns 0 if the constraints are satisfied, a positive
14116 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014117 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014118static int
14119xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14120 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014121{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014122 /*
14123 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14124 *
14125 * SPEC (1) "The values of the properties of a complex type definition must
14126 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014127 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014128 * Sub-components (§5.3)."
14129 */
14130 if ((type->baseType != NULL) &&
14131 (IS_SIMPLE_TYPE(type->baseType)) &&
14132 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14133 /*
14134 * SPEC (2) "If the {base type definition} is a simple type definition,
14135 * the {derivation method} must be extension."
14136 */
14137 xmlSchemaPCustomErr(pctxt,
14138 XML_SCHEMAP_SRC_CT_1,
14139 NULL, type, NULL,
14140 "If the base type is a simple type, the derivation method must be "
14141 "'extension'", NULL);
14142 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014143 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014144 /*
14145 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14146 * definition·. That is, it must be possible to reach the ·ur-type
14147 * definition by repeatedly following the {base type definition}."
14148 *
14149 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14150 *
14151 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014152 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014153 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14154 * must not have {type definition}s which are or are derived from ID."
14155 *
14156 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14157 */
14158 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014159}
14160
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014161static int
14162xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14163 xmlSchemaTypePtr typeB)
14164{
14165 /*
14166 * TODO: This should implement component-identity
14167 * in the future.
14168 */
14169 if ((typeA == NULL) || (typeB == NULL))
14170 return (0);
14171 return (typeA == typeB);
14172}
14173
14174/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014175 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014176 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014177 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014178 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014179 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014180 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014181 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014182 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14183 *
14184 * STATUS: completed
14185 *
14186 * Returns 0 if the constraints are satisfied, or 1
14187 * if not.
14188 */
14189static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014190xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014191 xmlSchemaTypePtr baseType,
14192 int set)
14193{
14194 int equal = xmlSchemaAreEqualTypes(type, baseType);
14195 /* TODO: Error codes. */
14196 /*
14197 * SPEC "For a complex type definition (call it D, for derived)
14198 * to be validly derived from a type definition (call this
14199 * B, for base) given a subset of {extension, restriction}
14200 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014201 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014202 if (! equal) {
14203 /*
14204 * SPEC (1) "If B and D are not the same type definition, then the
14205 * {derivation method} of D must not be in the subset."
14206 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014207 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014208 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014209 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014210 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014211 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014212 } else {
14213 /*
14214 * SPEC (2.1) "B and D must be the same type definition."
14215 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014216 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014217 }
14218 /*
14219 * SPEC (2.2) "B must be D's {base type definition}."
14220 */
14221 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014222 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014223 /*
14224 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14225 * definition·."
14226 */
14227 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014228 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014229
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014230 if (IS_COMPLEX_TYPE(type->baseType)) {
14231 /*
14232 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14233 * must be validly derived from B given the subset as defined by this
14234 * constraint."
14235 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014236 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014237 baseType, set));
14238 } else {
14239 /*
14240 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14241 * must be validly derived from B given the subset as defined in Type
14242 * Derivation OK (Simple) (§3.14.6).
14243 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014244 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14245 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014246}
14247
14248/**
14249 * xmlSchemaCheckCOSDerivedOK:
14250 * @type: the derived simple type definition
14251 * @baseType: the base type definition
14252 *
14253 * Calls:
14254 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014255 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014256 * Checks wheter @type can be validly derived from @baseType.
14257 *
14258 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014259 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014260static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014261xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014262 xmlSchemaTypePtr baseType,
14263 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014264{
14265 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014266 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014267 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014268 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014269}
14270
William M. Brack2f2a6632004-08-20 23:09:47 +000014271/**
14272 * xmlSchemaCheckCOSCTExtends:
14273 * @ctxt: the schema parser context
14274 * @type: the complex type definition
14275 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014276 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014277 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014278 * Derivation Valid (Extension) (cos-ct-extends)
14279 *
14280 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014281 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014282 * (1.5)
14283 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014284 *
14285 * Returns 0 if the constraints are satisfied, a positive
14286 * error code if not and -1 if an internal error occured.
14287 */
14288static int
14289xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14290 xmlSchemaTypePtr type)
14291{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014292 xmlSchemaTypePtr base = type->baseType;
14293 /*
14294 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14295 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014296 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014297 /*
14298 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014299 * then all of the following must be true:"
14300 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014301 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14302 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014303 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014304 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014305 */
14306 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14307 xmlSchemaPCustomErr(ctxt,
14308 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14309 NULL, type, NULL,
14310 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014311 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014312 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14313 }
14314 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014315 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014316 * uses}
14317 * of the complex type definition itself, that is, for every attribute
14318 * use in the {attribute uses} of the {base type definition}, there
14319 * must be an attribute use in the {attribute uses} of the complex
14320 * type definition itself whose {attribute declaration} has the same
14321 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014322 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014323 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014324 * NOTE (1.2): This will be already satisfied by the way the attribute
14325 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14326 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014327 */
14328
14329 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014330 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14331 * definition must also have one, and the base type definition's
14332 * {attribute wildcard}'s {namespace constraint} must be a subset
14333 * of the complex type definition's {attribute wildcard}'s {namespace
14334 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014335 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014336 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014337 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014338 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014339 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014340 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014341 if ((type->contentTypeDef != NULL) &&
14342 (type->contentTypeDef == base->contentTypeDef)) {
14343 /*
14344 * SPEC (1.4.1) "The {content type} of the {base type definition}
14345 * and the {content type} of the complex type definition itself
14346 * must be the same simple type definition"
14347 * PASS
14348 */
14349 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14350 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14351 /*
14352 * SPEC (1.4.2) "The {content type} of both the {base type
14353 * definition} and the complex type definition itself must
14354 * be empty."
14355 * PASS
14356 */
14357 } else {
14358 /*
14359 * SPEC (1.4.3) "All of the following must be true:"
14360 */
14361 if (type->subtypes == NULL) {
14362 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014363 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014364 * definition itself must specify a particle.
14365 */
14366 xmlSchemaPCustomErr(ctxt,
14367 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14368 NULL, type, NULL,
14369 "The content type must specify a particle", NULL);
14370 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14371 }
14372 /*
14373 * SPEC (1.4.3.2) "One of the following must be true:"
14374 */
14375 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14376 /*
14377 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14378 * definition} must be empty.
14379 * PASS
14380 */
14381 } else {
14382 /*
14383 * SPEC (1.4.3.2.2) "All of the following must be true:"
14384 */
14385 if ((type->contentType != base->contentType) ||
14386 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14387 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14388 /*
14389 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14390 * or both must be element-only."
14391 */
14392 xmlSchemaPCustomErr(ctxt,
14393 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14394 NULL, type, NULL,
14395 "The content type of both, the type and its base "
14396 "type, must either 'mixed' or 'element-only'", NULL);
14397 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014398 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014399 /*
14400 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14401 * complex type definition must be a ·valid extension·
14402 * of the {base type definition}'s particle, as defined
14403 * in Particle Valid (Extension) (§3.9.6)."
14404 *
14405 * NOTE that we won't check "Particle Valid (Extension)",
14406 * since it is ensured by the derivation process in
14407 * xmlSchemaTypeFixup(). We need to implement this when heading
14408 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014409 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014410 }
14411 /*
14412 * TODO (1.5)
14413 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014414 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014415 } else {
14416 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014417 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014418 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014419 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014420 if (type->contentTypeDef != base) {
14421 /*
14422 * SPEC (2.1) "The {content type} must be the same simple type
14423 * definition."
14424 */
14425 xmlSchemaPCustomErr(ctxt,
14426 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14427 NULL, type, NULL,
14428 "The content type must be the simple base type", NULL);
14429 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14430 }
14431 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14432 /*
14433 * SPEC (2.2) "The {final} of the {base type definition} must not
14434 * contain extension"
14435 * NOTE that this is the same as (1.1).
14436 */
14437 xmlSchemaPCustomErr(ctxt,
14438 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14439 NULL, type, NULL,
14440 "The 'final' of the base type definition "
14441 "contains 'extension'", NULL);
14442 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014443 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014444 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014445 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014446}
14447
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014448/**
14449 * xmlSchemaCheckDerivationOKRestriction:
14450 * @ctxt: the schema parser context
14451 * @type: the complex type definition
14452 *
14453 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014454 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014455 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14456 *
14457 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014458 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014459 * (5.4.2), (5.2.2.1)
14460 *
14461 * Returns 0 if the constraints are satisfied, a positive
14462 * error code if not and -1 if an internal error occured.
14463 */
14464static int
14465xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14466 xmlSchemaTypePtr type)
14467{
14468 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014469
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014470 /*
14471 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14472 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014473 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014474 base = type->baseType;
14475 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14476 /*
14477 * SPEC (1) "The {base type definition} must be a complex type
14478 * definition whose {final} does not contain restriction."
14479 */
14480 xmlSchemaPCustomErr(ctxt,
14481 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14482 NULL, type, NULL,
14483 "The 'final' of the base type definition "
14484 "contains 'restriction'", NULL);
14485 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14486 }
14487 /*
14488 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14489 *
14490 * SPEC (5) "One of the following must be true:"
14491 */
14492 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14493 /*
14494 * SPEC (5.1) "The {base type definition} must be the
14495 * ·ur-type definition·."
14496 * PASS
14497 */
14498 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14499 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14500 /*
14501 * SPEC (5.2.1) "The {content type} of the complex type definition
14502 * must be a simple type definition"
14503 *
14504 * SPEC (5.2.2) "One of the following must be true:"
14505 */
14506 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14507 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14508 /*
14509 * SPEC (5.2.2.1) "The {content type} of the {base type
14510 * definition} must be a simple type definition from which
14511 * the {content type} is validly derived given the empty
14512 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14513 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014514 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014515 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14516 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014517 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014518 /*
14519 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14520 * and have a particle which is ·emptiable· as defined in
14521 * Particle Emptiable (§3.9.6)."
14522 * PASS
14523 */
14524 } else {
14525 xmlSchemaPCustomErr(ctxt,
14526 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14527 NULL, type, NULL,
14528 "The content type of the base type must be either "
14529 "a simple type or 'mixed' and an emptiable particle", NULL);
14530 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14531 }
14532 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14533 /*
14534 * SPEC (5.3.1) "The {content type} of the complex type itself must
14535 * be empty"
14536 */
14537 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14538 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014539 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014540 * definition} must also be empty."
14541 * PASS
14542 */
14543 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14544 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14545 xmlSchemaIsParticleEmptiable(
14546 (xmlSchemaParticlePtr) base->subtypes)) {
14547 /*
14548 * SPEC (5.3.2.2) "The {content type} of the {base type
14549 * definition} must be elementOnly or mixed and have a particle
14550 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14551 * PASS
14552 */
14553 } else {
14554 xmlSchemaPCustomErr(ctxt,
14555 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14556 NULL, type, NULL,
14557 "The content type of the base type must be either "
14558 "empty or 'mixed' (or 'elements-only') and an emptiable "
14559 "particle", NULL);
14560 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14561 }
14562 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014563 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014564 /*
14565 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14566 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014567 */
14568 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14569 /*
14570 * SPEC (5.4.1.2) "The {content type} of the complex type
14571 * definition itself and of the {base type definition} must be
14572 * mixed"
14573 */
14574 xmlSchemaPCustomErr(ctxt,
14575 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14576 NULL, type, NULL,
14577 "If the content type is 'mixed', then the content type of the "
14578 "base type must also be 'mixed'", NULL);
14579 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14580 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014581 /*
14582 * SPEC (5.4.2) "The particle of the complex type definition itself
14583 * must be a ·valid restriction· of the particle of the {content
14584 * type} of the {base type definition} as defined in Particle Valid
14585 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014586 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014587 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014588 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014589 } else {
14590 xmlSchemaPCustomErr(ctxt,
14591 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14592 NULL, type, NULL,
14593 "The type is not a valid restriction of its base type", NULL);
14594 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14595 }
14596 return (0);
14597}
14598
14599/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014600 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014601 * @ctxt: the schema parser context
14602 * @type: the complex type definition
14603 *
14604 * (3.4.6) Constraints on Complex Type Definition Schema Components
14605 *
14606 * Returns 0 if the constraints are satisfied, a positive
14607 * error code if not and -1 if an internal error occured.
14608 */
14609static int
14610xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14611 xmlSchemaTypePtr type)
14612{
14613 int ret;
14614 /*
14615 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014616 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014617 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14618 if (ret != 0)
14619 return (ret);
14620 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14621 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14622 else
14623 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14624 return (ret);
14625}
14626
14627/**
14628 * xmlSchemaCheckSRCCT:
14629 * @ctxt: the schema parser context
14630 * @type: the complex type definition
14631 *
14632 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014633 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014634 * Complex Type Definition Representation OK (src-ct)
14635 *
14636 * Returns 0 if the constraints are satisfied, a positive
14637 * error code if not and -1 if an internal error occured.
14638 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014639static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014640xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014641 xmlSchemaTypePtr type)
14642{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014643 xmlSchemaTypePtr base;
14644 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014645
14646 /*
14647 * TODO: Adjust the error codes here, as I used
14648 * XML_SCHEMAP_SRC_CT_1 only yet.
14649 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014650 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014651 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014652 /*
14653 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014654 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014655 * must be a complex type definition;
14656 */
14657 if (! IS_COMPLEX_TYPE(base)) {
14658 xmlChar *str = NULL;
14659 xmlSchemaPCustomErr(ctxt,
14660 XML_SCHEMAP_SRC_CT_1,
14661 NULL, type, type->node,
14662 "If using <complexContent>, the base type is expected to be "
14663 "a complex type. The base type '%s' is a simple type",
14664 xmlSchemaFormatQName(&str, base->targetNamespace,
14665 base->name));
14666 FREE_AND_NULL(str)
14667 return (XML_SCHEMAP_SRC_CT_1);
14668 }
14669 } else {
14670 /*
14671 * SPEC
14672 * 2 If the <simpleContent> alternative is chosen, all of the
14673 * following must be true:
14674 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14675 * base [attribute] must be one of the following:
14676 */
14677 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014678 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014679 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14680 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014681 /*
14682 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014683 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014684 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014685 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014686 xmlSchemaPCustomErr(ctxt,
14687 XML_SCHEMAP_SRC_CT_1,
14688 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014689 "If using <simpleContent> and <restriction>, the base "
14690 "type must be a complex type. The base type '%s' is "
14691 "a simple type",
14692 xmlSchemaFormatQName(&str, base->targetNamespace,
14693 base->name));
14694 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014695 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014696 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014697 } else {
14698 /* Base type is a complex type. */
14699 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14700 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14701 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014702 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014703 * simple type definition;
14704 * PASS
14705 */
14706 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014707 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014708 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014709 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014710 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014711 type->name);
14712 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014713 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014714 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14715 (type->flags &
14716 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014717
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014718 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014719 * 2.1.2 only if the <restriction> alternative is also
14720 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014721 * is mixed and a particle emptiable.
14722 */
14723 if (! xmlSchemaIsParticleEmptiable(
14724 (xmlSchemaParticlePtr) base->subtypes)) {
14725 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014726 } else
14727 /*
14728 * Attention: at this point the <simpleType> child is in
14729 * ->contentTypeDef (put there during parsing).
14730 */
14731 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014732 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014733 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014734 * 2.2 If clause 2.1.2 above is satisfied, then there
14735 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014736 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014737 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014738 /* TODO: Change error code to ..._SRC_CT_2_2. */
14739 xmlSchemaPCustomErr(ctxt,
14740 XML_SCHEMAP_SRC_CT_1,
14741 NULL, type, NULL,
14742 "A <simpleType> is expected among the children "
14743 "of <restriction>, if <simpleContent> is used and "
14744 "the base type '%s' is a complex type",
14745 xmlSchemaFormatQName(&str, base->targetNamespace,
14746 base->name));
14747 FREE_AND_NULL(str)
14748 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014749 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014750 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014751 ret = XML_SCHEMAP_SRC_CT_1;
14752 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014753 }
14754 if (ret > 0) {
14755 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014756 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014757 xmlSchemaPCustomErr(ctxt,
14758 XML_SCHEMAP_SRC_CT_1,
14759 NULL, type, NULL,
14760 "If <simpleContent> and <restriction> is used, the "
14761 "base type must be a simple type or a complex type with "
14762 "mixed content and particle emptiable. The base type "
14763 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014764 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014765 base->name));
14766 } else {
14767 xmlSchemaPCustomErr(ctxt,
14768 XML_SCHEMAP_SRC_CT_1,
14769 NULL, type, NULL,
14770 "If <simpleContent> and <extension> is used, the "
14771 "base type must be a simple type. The base type '%s' "
14772 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014773 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014774 base->name));
14775 }
14776 FREE_AND_NULL(str)
14777 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014778 }
14779 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014780 * SPEC (3) "The corresponding complex type definition component must
14781 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014782 * Definition Schema Components (§3.4.6);"
14783 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014784 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014785 /*
14786 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014787 * above for {attribute wildcard} is satisfied, the intensional
14788 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014789 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014790 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014791 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014792 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014793}
William M. Brack2f2a6632004-08-20 23:09:47 +000014794
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014795#ifdef ENABLE_PARTICLE_RESTRICTION
14796/**
14797 * xmlSchemaCheckParticleRangeOK:
14798 * @ctxt: the schema parser context
14799 * @type: the complex type definition
14800 *
14801 * (3.9.6) Constraints on Particle Schema Components
14802 * Schema Component Constraint:
14803 * Occurrence Range OK (range-ok)
14804 *
14805 * STATUS: complete
14806 *
14807 * Returns 0 if the constraints are satisfied, a positive
14808 * error code if not and -1 if an internal error occured.
14809 */
14810static int
14811xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14812 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014813{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014814 if (rmin < bmin)
14815 return (1);
14816 if ((bmax != UNBOUNDED) &&
14817 (rmax > bmax))
14818 return (1);
14819 return (0);
14820}
14821
14822/**
14823 * xmlSchemaCheckRCaseNameAndTypeOK:
14824 * @ctxt: the schema parser context
14825 * @r: the restricting element declaration particle
14826 * @b: the base element declaration particle
14827 *
14828 * (3.9.6) Constraints on Particle Schema Components
14829 * Schema Component Constraint:
14830 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14831 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014832 *
14833 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014834 * MISSING (3.2.3)
14835 * CLARIFY: (3.2.2)
14836 *
14837 * Returns 0 if the constraints are satisfied, a positive
14838 * error code if not and -1 if an internal error occured.
14839 */
14840static int
14841xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14842 xmlSchemaParticlePtr r,
14843 xmlSchemaParticlePtr b)
14844{
14845 xmlSchemaElementPtr elemR, elemB;
14846
14847 /* TODO: Error codes (rcase-NameAndTypeOK). */
14848 elemR = (xmlSchemaElementPtr) r->children;
14849 elemB = (xmlSchemaElementPtr) b->children;
14850 /*
14851 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14852 * the same."
14853 */
14854 if ((elemR != elemB) &&
14855 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14856 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14857 return (1);
14858 /*
14859 * SPEC (2) "R's occurrence range is a valid restriction of B's
14860 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14861 */
14862 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14863 b->minOccurs, b->maxOccurs) != 0)
14864 return (1);
14865 /*
14866 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14867 * {scope} are global."
14868 */
14869 if (elemR == elemB)
14870 return (0);
14871 /*
14872 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14873 */
14874 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14875 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14876 return (1);
14877 /*
14878 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14879 * or is not fixed, or R's declaration's {value constraint} is fixed
14880 * with the same value."
14881 */
14882 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14883 ((elemR->value == NULL) ||
14884 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14885 /* TODO: Equality of the initial value or normalized or canonical? */
14886 (! xmlStrEqual(elemR->value, elemB->value))))
14887 return (1);
14888 /*
14889 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14890 * definitions} is a subset of B's declaration's {identity-constraint
14891 * definitions}, if any."
14892 */
14893 if (elemB->idcs != NULL) {
14894 /* TODO */
14895 }
14896 /*
14897 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14898 * superset of B's declaration's {disallowed substitutions}."
14899 */
14900 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14901 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14902 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14903 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14904 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14905 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14906 return (1);
14907 /*
14908 * SPEC (3.2.5) "R's {type definition} is validly derived given
14909 * {extension, list, union} from B's {type definition}"
14910 *
14911 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14912 * set, if the corresponding constraints handle "restriction" and
14913 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014914 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014915 */
14916 {
14917 int set = 0;
14918
14919 set |= SUBSET_EXTENSION;
14920 set |= SUBSET_LIST;
14921 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014922 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014923 elemB->subtypes, set) != 0)
14924 return (1);
14925 }
14926 return (0);
14927}
14928
14929/**
14930 * xmlSchemaCheckRCaseNSCompat:
14931 * @ctxt: the schema parser context
14932 * @r: the restricting element declaration particle
14933 * @b: the base wildcard particle
14934 *
14935 * (3.9.6) Constraints on Particle Schema Components
14936 * Schema Component Constraint:
14937 * Particle Derivation OK (Elt:Any -- NSCompat)
14938 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014939 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014940 * STATUS: complete
14941 *
14942 * Returns 0 if the constraints are satisfied, a positive
14943 * error code if not and -1 if an internal error occured.
14944 */
14945static int
14946xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14947 xmlSchemaParticlePtr r,
14948 xmlSchemaParticlePtr b)
14949{
14950 /* TODO:Error codes (rcase-NSCompat). */
14951 /*
14952 * SPEC "For an element declaration particle to be a ·valid restriction·
14953 * of a wildcard particle all of the following must be true:"
14954 *
14955 * SPEC (1) "The element declaration's {target namespace} is ·valid·
14956 * with respect to the wildcard's {namespace constraint} as defined by
14957 * Wildcard allows Namespace Name (§3.10.4)."
14958 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014959 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014960 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
14961 return (1);
14962 /*
14963 * SPEC (2) "R's occurrence range is a valid restriction of B's
14964 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14965 */
14966 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14967 b->minOccurs, b->maxOccurs) != 0)
14968 return (1);
14969
14970 return (0);
14971}
14972
14973/**
14974 * xmlSchemaCheckRCaseRecurseAsIfGroup:
14975 * @ctxt: the schema parser context
14976 * @r: the restricting element declaration particle
14977 * @b: the base model group particle
14978 *
14979 * (3.9.6) Constraints on Particle Schema Components
14980 * Schema Component Constraint:
14981 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
14982 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014983 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014984 * STATUS: TODO
14985 *
14986 * Returns 0 if the constraints are satisfied, a positive
14987 * error code if not and -1 if an internal error occured.
14988 */
14989static int
14990xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
14991 xmlSchemaParticlePtr r,
14992 xmlSchemaParticlePtr b)
14993{
14994 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
14995 TODO
14996 return (0);
14997}
14998
14999/**
15000 * xmlSchemaCheckRCaseNSSubset:
15001 * @ctxt: the schema parser context
15002 * @r: the restricting wildcard particle
15003 * @b: the base wildcard particle
15004 *
15005 * (3.9.6) Constraints on Particle Schema Components
15006 * Schema Component Constraint:
15007 * Particle Derivation OK (Any:Any -- NSSubset)
15008 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015009 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015010 * STATUS: complete
15011 *
15012 * Returns 0 if the constraints are satisfied, a positive
15013 * error code if not and -1 if an internal error occured.
15014 */
15015static int
15016xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15017 xmlSchemaParticlePtr r,
15018 xmlSchemaParticlePtr b,
15019 int isAnyTypeBase)
15020{
15021 /* TODO: Error codes (rcase-NSSubset). */
15022 /*
15023 * SPEC (1) "R's occurrence range is a valid restriction of B's
15024 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15025 */
15026 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15027 b->minOccurs, b->maxOccurs))
15028 return (1);
15029 /*
15030 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15031 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15032 */
15033 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15034 (xmlSchemaWildcardPtr) b->children))
15035 return (1);
15036 /*
15037 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15038 * definition·, R's {process contents} must be identical to or stronger
15039 * than B's {process contents}, where strict is stronger than lax is
15040 * stronger than skip."
15041 */
15042 if (! isAnyTypeBase) {
15043 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15044 ((xmlSchemaWildcardPtr) b->children)->processContents)
15045 return (1);
15046 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015047
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015048 return (0);
15049}
15050
15051/**
15052 * xmlSchemaCheckCOSParticleRestrict:
15053 * @ctxt: the schema parser context
15054 * @type: the complex type definition
15055 *
15056 * (3.9.6) Constraints on Particle Schema Components
15057 * Schema Component Constraint:
15058 * Particle Valid (Restriction) (cos-particle-restrict)
15059 *
15060 * STATUS: TODO
15061 *
15062 * Returns 0 if the constraints are satisfied, a positive
15063 * error code if not and -1 if an internal error occured.
15064 */
15065static int
15066xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15067 xmlSchemaParticlePtr r,
15068 xmlSchemaParticlePtr b)
15069{
15070 int ret = 0;
15071
15072 /*part = GET_PARTICLE(type);
15073 basePart = GET_PARTICLE(base);
15074 */
15075
15076 TODO
15077
15078 /*
15079 * SPEC (1) "They are the same particle."
15080 */
15081 if (r == b)
15082 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015083
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015084
15085 return (0);
15086}
15087
15088/**
15089 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15090 * @ctxt: the schema parser context
15091 * @r: the model group particle
15092 * @b: the base wildcard particle
15093 *
15094 * (3.9.6) Constraints on Particle Schema Components
15095 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015096 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015097 * NSRecurseCheckCardinality)
15098 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015099 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015100 * STATUS: TODO: subst-groups
15101 *
15102 * Returns 0 if the constraints are satisfied, a positive
15103 * error code if not and -1 if an internal error occured.
15104 */
15105static int
15106xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15107 xmlSchemaParticlePtr r,
15108 xmlSchemaParticlePtr b)
15109{
15110 xmlSchemaParticlePtr part;
15111 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15112 if ((r->children == NULL) || (r->children->children == NULL))
15113 return (-1);
15114 /*
15115 * SPEC "For a group particle to be a ·valid restriction· of a
15116 * wildcard particle..."
15117 *
15118 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015119 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015120 * Particle Valid (Restriction) (§3.9.6)."
15121 */
15122 part = (xmlSchemaParticlePtr) r->children->children;
15123 do {
15124 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15125 return (1);
15126 part = (xmlSchemaParticlePtr) part->next;
15127 } while (part != NULL);
15128 /*
15129 * SPEC (2) "The effective total range of the group [...] is a
15130 * valid restriction of B's occurrence range as defined by
15131 * Occurrence Range OK (§3.9.6)."
15132 */
15133 if (xmlSchemaCheckParticleRangeOK(
15134 xmlSchemaGetParticleTotalRangeMin(r),
15135 xmlSchemaGetParticleTotalRangeMax(r),
15136 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015137 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015138 return (0);
15139}
15140
15141/**
15142 * xmlSchemaCheckRCaseRecurse:
15143 * @ctxt: the schema parser context
15144 * @r: the <all> or <sequence> model group particle
15145 * @b: the base <all> or <sequence> model group particle
15146 *
15147 * (3.9.6) Constraints on Particle Schema Components
15148 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015149 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015150 Recurse)
15151 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015152 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015153 * STATUS: ?
15154 * TODO: subst-groups
15155 *
15156 * Returns 0 if the constraints are satisfied, a positive
15157 * error code if not and -1 if an internal error occured.
15158 */
15159static int
15160xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15161 xmlSchemaParticlePtr r,
15162 xmlSchemaParticlePtr b)
15163{
15164 /* xmlSchemaParticlePtr part; */
15165 /* TODO: Error codes (rcase-Recurse). */
15166 if ((r->children == NULL) || (b->children == NULL) ||
15167 (r->children->type != b->children->type))
15168 return (-1);
15169 /*
15170 * SPEC "For an all or sequence group particle to be a ·valid
15171 * restriction· of another group particle with the same {compositor}..."
15172 *
15173 * SPEC (1) "R's occurrence range is a valid restriction of B's
15174 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15175 */
15176 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15177 b->minOccurs, b->maxOccurs))
15178 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015179
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015180
15181 return (0);
15182}
15183
15184#endif
15185
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015186#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15187 xmlSchemaPCustomErrExt(pctxt, \
15188 XML_SCHEMAP_INVALID_FACET_VALUE, \
15189 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15190 "It is an error for both '%s' and '%s' to be specified on the "\
15191 "same type definition", \
15192 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15193 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15194
15195#define FACET_RESTR_ERR(fac1, msg) \
15196 xmlSchemaPCustomErr(pctxt, \
15197 XML_SCHEMAP_INVALID_FACET_VALUE, \
15198 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015199 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015200
15201#define FACET_RESTR_FIXED_ERR(fac) \
15202 xmlSchemaPCustomErr(pctxt, \
15203 XML_SCHEMAP_INVALID_FACET_VALUE, \
15204 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15205 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015206 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015207
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015208static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015209xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15210 xmlSchemaFacetPtr facet1,
15211 xmlSchemaFacetPtr facet2,
15212 int lessGreater,
15213 int orEqual,
15214 int ofBase)
15215{
15216 xmlChar *msg = NULL;
15217
15218 msg = xmlStrdup(BAD_CAST "'");
15219 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15220 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15221 if (lessGreater == 0)
15222 msg = xmlStrcat(msg, BAD_CAST " equal to");
15223 if (lessGreater == 1)
15224 msg = xmlStrcat(msg, BAD_CAST " greater than");
15225 else
15226 msg = xmlStrcat(msg, BAD_CAST " less than");
15227
15228 if (orEqual)
15229 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15230 msg = xmlStrcat(msg, BAD_CAST " '");
15231 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15232 if (ofBase)
15233 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15234 else
15235 msg = xmlStrcat(msg, BAD_CAST "'");
15236
15237 xmlSchemaPCustomErr(pctxt,
15238 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015239 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015240 (const char *) msg, NULL);
15241
15242 if (msg != NULL)
15243 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015244}
15245
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015246static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015247xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15248 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015249{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015250 xmlSchemaTypePtr base = type->baseType;
15251 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015252 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015253 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15254 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15255 fmininc = NULL, fmaxinc = NULL,
15256 fminexc = NULL, fmaxexc = NULL,
15257 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15258 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15259 bfmininc = NULL, bfmaxinc = NULL,
15260 bfminexc = NULL, bfmaxexc = NULL;
15261 int res, err = 0, fixedErr;
15262 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015263 * 3 The {facets} of R are the union of S and the {facets}
15264 * of B, eliminating duplicates. To eliminate duplicates,
15265 * when a facet of the same kind occurs in both S and the
15266 * {facets} of B, the one in the {facets} of B is not
15267 * included, with the exception of enumeration and pattern
15268 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015269 * are allowed.
15270 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015271
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015272 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15273 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015274
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015275 last = type->facetSet;
15276 if (last != NULL)
15277 while (last->next != NULL)
15278 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015279
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015280 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15281 facet = cur->facet;
15282 switch (facet->type) {
15283 case XML_SCHEMA_FACET_LENGTH:
15284 flength = facet; break;
15285 case XML_SCHEMA_FACET_MINLENGTH:
15286 fminlen = facet; break;
15287 case XML_SCHEMA_FACET_MININCLUSIVE:
15288 fmininc = facet; break;
15289 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15290 fminexc = facet; break;
15291 case XML_SCHEMA_FACET_MAXLENGTH:
15292 fmaxlen = facet; break;
15293 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15294 fmaxinc = facet; break;
15295 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15296 fmaxexc = facet; break;
15297 case XML_SCHEMA_FACET_TOTALDIGITS:
15298 ftotdig = facet; break;
15299 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15300 ffracdig = facet; break;
15301 default:
15302 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015303 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015304 }
15305 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15306 facet = cur->facet;
15307 switch (facet->type) {
15308 case XML_SCHEMA_FACET_LENGTH:
15309 bflength = facet; break;
15310 case XML_SCHEMA_FACET_MINLENGTH:
15311 bfminlen = facet; break;
15312 case XML_SCHEMA_FACET_MININCLUSIVE:
15313 bfmininc = facet; break;
15314 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15315 bfminexc = facet; break;
15316 case XML_SCHEMA_FACET_MAXLENGTH:
15317 bfmaxlen = facet; break;
15318 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15319 bfmaxinc = facet; break;
15320 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15321 bfmaxexc = facet; break;
15322 case XML_SCHEMA_FACET_TOTALDIGITS:
15323 bftotdig = facet; break;
15324 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15325 bffracdig = facet; break;
15326 default:
15327 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015328 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015329 }
15330 err = 0;
15331 /*
15332 * length and minLength or maxLength (2.2) + (3.2)
15333 */
15334 if (flength && (fminlen || fmaxlen)) {
15335 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15336 "either of 'minLength' or 'maxLength' to be specified on "
15337 "the same type definition")
15338 }
15339 /*
15340 * Mutual exclusions in the same derivation step.
15341 */
15342 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015343 /*
15344 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015345 */
15346 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15347 }
15348 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015349 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015350 * SCC "minInclusive and minExclusive"
15351 */
15352 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015353 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015354
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015355 if (flength && bflength) {
15356 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015357 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015358 * The values have to be equal.
15359 */
15360 res = xmlSchemaCompareValues(flength->val, bflength->val);
15361 if (res == -2)
15362 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015363 if (res != 0)
15364 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15365 if ((res != 0) && (bflength->fixed)) {
15366 FACET_RESTR_FIXED_ERR(flength)
15367 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015368
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015369 }
15370 if (fminlen && bfminlen) {
15371 /*
15372 * SCC "minLength valid restriction"
15373 * minLength >= BASE minLength
15374 */
15375 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15376 if (res == -2)
15377 goto internal_error;
15378 if (res == -1)
15379 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15380 if ((res != 0) && (bfminlen->fixed)) {
15381 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015382 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015383 }
15384 if (fmaxlen && bfmaxlen) {
15385 /*
15386 * SCC "maxLength valid restriction"
15387 * maxLength <= BASE minLength
15388 */
15389 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15390 if (res == -2)
15391 goto internal_error;
15392 if (res == 1)
15393 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15394 if ((res != 0) && (bfmaxlen->fixed)) {
15395 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015396 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015397 }
15398 /*
15399 * SCC "length and minLength or maxLength"
15400 */
15401 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015402 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015403 if (flength) {
15404 if (! fminlen)
15405 flength = bflength;
15406 if (fminlen) {
15407 /* (1.1) length >= minLength */
15408 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15409 if (res == -2)
15410 goto internal_error;
15411 if (res == -1)
15412 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15413 }
15414 if (! fmaxlen)
15415 fmaxlen = bfmaxlen;
15416 if (fmaxlen) {
15417 /* (2.1) length <= maxLength */
15418 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15419 if (res == -2)
15420 goto internal_error;
15421 if (res == 1)
15422 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15423 }
15424 }
15425 if (fmaxinc) {
15426 /*
15427 * "maxInclusive"
15428 */
15429 if (fmininc) {
15430 /* SCC "maxInclusive >= minInclusive" */
15431 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15432 if (res == -2)
15433 goto internal_error;
15434 if (res == -1) {
15435 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15436 }
15437 }
15438 /*
15439 * SCC "maxInclusive valid restriction"
15440 */
15441 if (bfmaxinc) {
15442 /* maxInclusive <= BASE maxInclusive */
15443 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15444 if (res == -2)
15445 goto internal_error;
15446 if (res == 1)
15447 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15448 if ((res != 0) && (bfmaxinc->fixed)) {
15449 FACET_RESTR_FIXED_ERR(fmaxinc)
15450 }
15451 }
15452 if (bfmaxexc) {
15453 /* maxInclusive < BASE maxExclusive */
15454 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15455 if (res == -2)
15456 goto internal_error;
15457 if (res != -1) {
15458 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15459 }
15460 }
15461 if (bfmininc) {
15462 /* maxInclusive >= BASE minInclusive */
15463 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15464 if (res == -2)
15465 goto internal_error;
15466 if (res == -1) {
15467 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15468 }
15469 }
15470 if (bfminexc) {
15471 /* maxInclusive > BASE minExclusive */
15472 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15473 if (res == -2)
15474 goto internal_error;
15475 if (res != 1) {
15476 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15477 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015478 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015479 }
15480 if (fmaxexc) {
15481 /*
15482 * "maxExclusive >= minExclusive"
15483 */
15484 if (fminexc) {
15485 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15486 if (res == -2)
15487 goto internal_error;
15488 if (res == -1) {
15489 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15490 }
15491 }
15492 /*
15493 * "maxExclusive valid restriction"
15494 */
15495 if (bfmaxexc) {
15496 /* maxExclusive <= BASE maxExclusive */
15497 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15498 if (res == -2)
15499 goto internal_error;
15500 if (res == 1) {
15501 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15502 }
15503 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015504 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015505 }
15506 }
15507 if (bfmaxinc) {
15508 /* maxExclusive <= BASE maxInclusive */
15509 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15510 if (res == -2)
15511 goto internal_error;
15512 if (res == 1) {
15513 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15514 }
15515 }
15516 if (bfmininc) {
15517 /* maxExclusive > BASE minInclusive */
15518 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15519 if (res == -2)
15520 goto internal_error;
15521 if (res != 1) {
15522 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15523 }
15524 }
15525 if (bfminexc) {
15526 /* maxExclusive > BASE minExclusive */
15527 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15528 if (res == -2)
15529 goto internal_error;
15530 if (res != 1) {
15531 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15532 }
15533 }
15534 }
15535 if (fminexc) {
15536 /*
15537 * "minExclusive < maxInclusive"
15538 */
15539 if (fmaxinc) {
15540 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15541 if (res == -2)
15542 goto internal_error;
15543 if (res != -1) {
15544 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15545 }
15546 }
15547 /*
15548 * "minExclusive valid restriction"
15549 */
15550 if (bfminexc) {
15551 /* minExclusive >= BASE minExclusive */
15552 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15553 if (res == -2)
15554 goto internal_error;
15555 if (res == -1) {
15556 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15557 }
15558 if ((res != 0) && (bfminexc->fixed)) {
15559 FACET_RESTR_FIXED_ERR(fminexc)
15560 }
15561 }
15562 if (bfmaxinc) {
15563 /* minExclusive <= BASE maxInclusive */
15564 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15565 if (res == -2)
15566 goto internal_error;
15567 if (res == 1) {
15568 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15569 }
15570 }
15571 if (bfmininc) {
15572 /* minExclusive >= BASE minInclusive */
15573 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15574 if (res == -2)
15575 goto internal_error;
15576 if (res == -1) {
15577 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15578 }
15579 }
15580 if (bfmaxexc) {
15581 /* minExclusive < BASE maxExclusive */
15582 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15583 if (res == -2)
15584 goto internal_error;
15585 if (res != -1) {
15586 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15587 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015588 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015589 }
15590 if (fmininc) {
15591 /*
15592 * "minInclusive < maxExclusive"
15593 */
15594 if (fmaxexc) {
15595 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15596 if (res == -2)
15597 goto internal_error;
15598 if (res != -1) {
15599 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15600 }
15601 }
15602 /*
15603 * "minExclusive valid restriction"
15604 */
15605 if (bfmininc) {
15606 /* minInclusive >= BASE minInclusive */
15607 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15608 if (res == -2)
15609 goto internal_error;
15610 if (res == -1) {
15611 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15612 }
15613 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015614 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015615 }
15616 }
15617 if (bfmaxinc) {
15618 /* minInclusive <= BASE maxInclusive */
15619 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15620 if (res == -2)
15621 goto internal_error;
15622 if (res == -1) {
15623 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15624 }
15625 }
15626 if (bfminexc) {
15627 /* minInclusive > BASE minExclusive */
15628 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15629 if (res == -2)
15630 goto internal_error;
15631 if (res != 1)
15632 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15633 }
15634 if (bfmaxexc) {
15635 /* minInclusive < BASE maxExclusive */
15636 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15637 if (res == -2)
15638 goto internal_error;
15639 if (res != -1)
15640 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15641 }
15642 }
15643 if (ftotdig && bftotdig) {
15644 /*
15645 * SCC " totalDigits valid restriction"
15646 * totalDigits <= BASE totalDigits
15647 */
15648 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15649 if (res == -2)
15650 goto internal_error;
15651 if (res == 1)
15652 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15653 -1, 1, 1);
15654 if ((res != 0) && (bftotdig->fixed)) {
15655 FACET_RESTR_FIXED_ERR(ftotdig)
15656 }
15657 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015658 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015659 /*
15660 * SCC "fractionDigits valid restriction"
15661 * fractionDigits <= BASE fractionDigits
15662 */
15663 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15664 if (res == -2)
15665 goto internal_error;
15666 if (res == 1)
15667 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15668 -1, 1, 1);
15669 if ((res != 0) && (bffracdig->fixed)) {
15670 FACET_RESTR_FIXED_ERR(ffracdig)
15671 }
15672 }
15673 /*
15674 * SCC "fractionDigits less than or equal to totalDigits"
15675 */
15676 if (! ftotdig)
15677 ftotdig = bftotdig;
15678 if (! ffracdig)
15679 ffracdig = bffracdig;
15680 if (ftotdig && ffracdig) {
15681 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15682 if (res == -2)
15683 goto internal_error;
15684 if (res == 1)
15685 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15686 -1, 1, 0);
15687 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015688 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015689 * *Enumerations* won' be added here, since only the first set
15690 * of enumerations in the ancestor-or-self axis is used
15691 * for validation, plus we need to use the base type of those
15692 * enumerations for whitespace.
15693 *
15694 * *Patterns*: won't be add here, since they are ORed at
15695 * type level and ANDed at ancestor level. This will
15696 * happed during validation by walking the base axis
15697 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015698 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015699 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15700 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015701 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015702 * Special handling of enumerations and patterns.
15703 * TODO: hmm, they should not appear in the set, so remove this.
15704 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015705 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015706 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015707 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015708 /*
15709 * Search for a duplicate facet in the current type.
15710 */
15711 link = type->facetSet;
15712 err = 0;
15713 fixedErr = 0;
15714 while (link != NULL) {
15715 facet = link->facet;
15716 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015717 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015718 case XML_SCHEMA_FACET_WHITESPACE:
15719 /*
15720 * The whitespace must be stronger.
15721 */
15722 if (facet->whitespace < bfacet->whitespace) {
15723 FACET_RESTR_ERR(flength,
15724 "The 'whitespace' value has to be equal to "
15725 "or stronger than the 'whitespace' value of "
15726 "the base type")
15727 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015728 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015729 (facet->whitespace != bfacet->whitespace)) {
15730 FACET_RESTR_FIXED_ERR(facet)
15731 }
15732 break;
15733 default:
15734 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015735 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015736 /* Duplicate found. */
15737 break;
15738 }
15739 link = link->next;
15740 }
15741 /*
15742 * If no duplicate was found: add the base types's facet
15743 * to the set.
15744 */
15745 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015746 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015747 xmlMalloc(sizeof(xmlSchemaFacetLink));
15748 if (link == NULL) {
15749 xmlSchemaPErrMemory(pctxt,
15750 "deriving facets, creating a facet link", NULL);
15751 return (-1);
15752 }
15753 link->facet = cur->facet;
15754 link->next = NULL;
15755 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015756 type->facetSet = link;
15757 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015758 last->next = link;
15759 last = link;
15760 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015761
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015762 }
15763
15764 return (0);
15765internal_error:
15766 xmlSchemaPCustomErr(pctxt,
15767 XML_SCHEMAP_INVALID_FACET_VALUE,
15768 NULL, type, NULL,
15769 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15770 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015771}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015772
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015773static int
15774xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15775 xmlSchemaTypePtr type)
15776{
15777 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15778 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015779 * The actual value is then formed by replacing any union type
15780 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015781 * {member type definitions}, in order.
15782 */
15783 link = type->memberTypes;
15784 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015785
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015786 if (IS_NOT_TYPEFIXED(link->type))
15787 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15788
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015789 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015790 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015791 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015792 link->type = subLink->type;
15793 if (subLink->next != NULL) {
15794 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015795 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015796 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015797 while (subLink != NULL) {
15798 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015799 xmlMalloc(sizeof(xmlSchemaTypeLink));
15800 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015801 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015802 NULL);
15803 return (-1);
15804 }
15805 newLink->type = subLink->type;
15806 prevLink->next = newLink;
15807 prevLink = newLink;
15808 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015809
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015810 subLink = subLink->next;
15811 }
15812 }
15813 }
15814 }
15815 link = link->next;
15816 }
15817 return (0);
15818}
15819
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015820static void
15821xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15822{
15823 int has = 0, needVal = 0, normVal = 0;
15824
15825 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15826 if (has) {
15827 needVal = (type->baseType->flags &
15828 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15829 normVal = (type->baseType->flags &
15830 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15831 }
15832 if (type->facets != NULL) {
15833 xmlSchemaFacetPtr fac;
15834
15835 for (fac = type->facets; fac != NULL; fac = fac->next) {
15836 switch (fac->type) {
15837 case XML_SCHEMA_FACET_WHITESPACE:
15838 break;
15839 case XML_SCHEMA_FACET_PATTERN:
15840 normVal = 1;
15841 has = 1;
15842 break;
15843 case XML_SCHEMA_FACET_ENUMERATION:
15844 needVal = 1;
15845 normVal = 1;
15846 has = 1;
15847 break;
15848 default:
15849 has = 1;
15850 break;
15851 }
15852 }
15853 }
15854 if (normVal)
15855 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15856 if (needVal)
15857 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15858 if (has)
15859 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15860
15861 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15862 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15863 /*
15864 * OPTIMIZE VAL TODO: Some facets need a computed value.
15865 */
15866 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15867 (prim->builtInType != XML_SCHEMAS_STRING)) {
15868 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15869 }
15870 }
15871}
15872
15873static int
15874xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15875{
15876
15877
15878 /*
15879 * Evaluate the whitespace-facet value.
15880 */
15881 if (VARIETY_LIST(type)) {
15882 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15883 return (0);
15884 } else if (VARIETY_UNION(type))
15885 return (0);
15886
15887 if (type->facetSet != NULL) {
15888 xmlSchemaFacetLinkPtr lin;
15889
15890 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15891 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15892 switch (lin->facet->whitespace) {
15893 case XML_SCHEMAS_FACET_PRESERVE:
15894 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15895 break;
15896 case XML_SCHEMAS_FACET_REPLACE:
15897 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15898 break;
15899 case XML_SCHEMAS_FACET_COLLAPSE:
15900 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15901 break;
15902 default:
15903 return (-1);
15904 }
15905 return (0);
15906 }
15907 }
15908 }
15909 /*
15910 * For all ·atomic· datatypes other than string (and types ·derived·
15911 * by ·restriction· from it) the value of whiteSpace is fixed to
15912 * collapse
15913 */
15914 {
15915 xmlSchemaTypePtr anc;
15916
15917 for (anc = type->baseType; anc != NULL &&
15918 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15919 anc = anc->baseType) {
15920
15921 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15922 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15923 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15924
15925 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15926 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15927 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15928
15929 } else
15930 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15931 break;
15932 }
15933 }
15934 return (0);
15935 }
15936 return (0);
15937}
15938
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015939/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015940 * xmlSchemaTypeFixup:
15941 * @typeDecl: the schema type definition
15942 * @ctxt: the schema parser context
15943 *
15944 * Fixes the content model of the type.
15945 */
15946static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015947xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015948 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015949{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015950 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015951 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015952 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15953 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015954 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015955 if (! IS_NOT_TYPEFIXED(type))
15956 return;
15957 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015958 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015959 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015960
15961 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015962 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015963 XML_SCHEMAP_INTERNAL,
15964 NULL, type, NULL,
15965 "Internal error: xmlSchemaTypeFixup, "
15966 "baseType is missing on '%s'", type->name);
15967 return;
15968 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015969
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015970 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015971 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015972
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015973 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015974 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015975 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015976 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015977 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015978 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15979 /*
15980 * Skip fixup if the base type is invalid.
15981 * TODO: Generate a warning!
15982 */
15983 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015984 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015985 /*
15986 * This basically checks if the base type can be derived.
15987 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015988 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015989 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
15990 return;
15991 }
15992 /*
15993 * Fixup the content type.
15994 */
15995 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
15996 /*
15997 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015998 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015999 if ((IS_COMPLEX_TYPE(baseType)) &&
16000 (baseType->contentTypeDef != NULL) &&
16001 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016002 xmlSchemaTypePtr contentBase, content;
16003 char buf[30];
16004 const xmlChar *tmpname;
16005 /*
16006 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016007 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016008 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016009 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016010 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016011 * SPEC (1.1) "the simple type definition corresponding to the
16012 * <simpleType> among the [children] of <restriction> if there
16013 * is one;"
16014 * Note that this "<simpleType> among the [children]" was put
16015 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016016 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016017 contentBase = type->contentTypeDef;
16018 type->contentTypeDef = NULL;
16019 } else {
16020 /*
16021 * (1.2) "...otherwise (<restriction> has no <simpleType>
16022 * among its [children]), the simple type definition which
16023 * is the {content type} of the ... base type."
16024 */
16025 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016026 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016027 /*
16028 * SPEC
16029 * "... a simple type definition which restricts the simple
16030 * type definition identified in clause 1.1 or clause 1.2
16031 * with a set of facet components"
16032 *
16033 * Create the anonymous simple type, which will be the content
16034 * type of the complex type.
16035 */
16036 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16037 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16038 content = xmlSchemaAddType(pctxt,
16039 pctxt->schema, tmpname, tmpname, type->node);
16040 if (content == NULL)
16041 return;
16042 /*
16043 * We will use the same node as for the <complexType>
16044 * to have it somehow anchored in the schema doc.
16045 */
16046 content->node = type->node;
16047 content->type = XML_SCHEMA_TYPE_SIMPLE;
16048 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16049 content->baseType = contentBase;
16050 /*
16051 * Move the facets, previously anchored on the complexType.
16052 */
16053 content->facets = type->facets;
16054 type->facets = NULL;
16055 content->facetSet = type->facetSet;
16056 type->facetSet = NULL;
16057
16058 type->contentTypeDef = content;
16059 if (IS_NOT_TYPEFIXED(contentBase))
16060 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16061 xmlSchemaTypeFixup(content, pctxt, NULL);
16062
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016063 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16064 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16065 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16066 /*
16067 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16068 * an emptiable particle, then a simple type definition which
16069 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016070 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016071 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016072 (type->contentTypeDef->baseType == NULL)) {
16073 /*
16074 * TODO: Check if this ever happens.
16075 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016076 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016077 XML_SCHEMAP_INTERNAL,
16078 NULL, type, NULL,
16079 "Internal error: xmlSchemaTypeFixup, "
16080 "complex type '%s': the <simpleContent><restriction> "
16081 "is missing a <simpleType> child, but was not catched "
16082 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016083 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016084 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16085 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16086 /*
16087 * SPEC (3) If <extension> + base is <complexType> with
16088 * <simpleType> content, "...then the {content type} of that
16089 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016090 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016091 if (baseType->contentTypeDef == NULL) {
16092 /*
16093 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16094 * should have catched this already.
16095 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016096 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016097 XML_SCHEMAP_INTERNAL,
16098 NULL, type, NULL,
16099 "Internal error: xmlSchemaTypeFixup, "
16100 "complex type '%s': the <extension>ed base type is "
16101 "a complex type with no simple content type",
16102 type->name);
16103 }
16104 type->contentTypeDef = baseType->contentTypeDef;
16105 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16106 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16107 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016108 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016109 * "... then that simple type definition"
16110 */
16111 type->contentTypeDef = baseType;
16112 } else {
16113 /*
16114 * TODO: Check if this ever happens.
16115 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016116 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016117 XML_SCHEMAP_INTERNAL,
16118 NULL, type, NULL,
16119 "Internal error: xmlSchemaTypeFixup, "
16120 "complex type '%s' with <simpleContent>: unhandled "
16121 "derivation case", type->name);
16122 }
16123 } else {
16124 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016125 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016126 (xmlSchemaParticlePtr) type->subtypes;
16127 /*
16128 * Corresponds to <complexType><complexContent>...
16129 *
16130 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016131 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016132 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016133 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016134 * Compute the "effective content":
16135 * (2.1.1) + (2.1.2) + (2.1.3)
16136 */
16137 if ((particle == NULL) ||
16138 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16139 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16140 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16141 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16142 (particle->minOccurs == 0))) &&
16143 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016144 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016145 /*
16146 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16147 * a particle whose properties are as follows:..."
16148 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016149 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016150 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16151 * NOTE that we sill assign it the <complexType> node to
16152 * somehow anchor it in the doc.
16153 */
16154 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016155 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016156 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016157 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016158 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016159 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016160 type->node, 1, 1);
16161 if (particle == NULL)
16162 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016163 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016164 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016165 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016166 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016167 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016168 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16169 if (particle->children == NULL)
16170 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016171
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016172 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016173 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016174 dummySequence = 1;
16175 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16176 } else {
16177 /*
16178 * SPEC (2.1.5) "otherwise empty"
16179 */
16180 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016181 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016182 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016183 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016184 * SPEC (2.2) "otherwise the particle corresponding to the
16185 * <all>, <choice>, <group> or <sequence> among the
16186 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016187 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016188 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16189 }
16190 /*
16191 * Compute the "content type".
16192 */
16193 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016194 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016195 * SPEC (3.1) "If <restriction>..."
16196 * (3.1.1) + (3.1.2) */
16197 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16198 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16199 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16200 }
16201 } else {
16202 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016203 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016204 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016205 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16206 /*
16207 * SPEC (3.2.1)
16208 */
16209 type->contentType = baseType->contentType;
16210 type->subtypes = baseType->subtypes;
16211 /*
16212 * NOTE that the effective mixed is ignored here.
16213 */
16214 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16215 /*
16216 * SPEC (3.2.2)
16217 */
16218 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16219 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16220 } else {
16221 /*
16222 * SPEC (3.2.3)
16223 */
16224 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16225 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16226 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016227 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016228 * {particles} are..."
16229 */
16230 if (! dummySequence) {
16231 xmlSchemaTreeItemPtr effectiveContent =
16232 (xmlSchemaTreeItemPtr) type->subtypes;
16233 /*
16234 * Create the particle.
16235 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016236 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016237 type->node, 1, 1);
16238 if (particle == NULL)
16239 return;
16240 /*
16241 * Create the "sequence" model group.
16242 */
16243 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016244 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016245 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16246 if (particle->children == NULL)
16247 return;
16248 type->subtypes = (xmlSchemaTypePtr) particle;
16249 /*
16250 * SPEC "the particle of the {content type} of
16251 * the ... base ..."
16252 * Create a duplicate of the base type's particle
16253 * and assign its "term" to it.
16254 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016255 particle->children->children =
16256 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16257 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016258 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016259 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016260 if (particle->children->children == NULL)
16261 return;
16262 particle = (xmlSchemaParticlePtr)
16263 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016264 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016265 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16266 /*
16267 * SPEC "followed by the ·effective content·."
16268 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016269 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016270 } else {
16271 /*
16272 * This is the case when there is already an empty
16273 * <sequence> with minOccurs==maxOccurs==1.
16274 * Just add the base types's content type.
16275 * NOTE that, although we miss to add an intermediate
16276 * <sequence>, this should produce no difference to
16277 * neither the regex compilation of the content model,
16278 * nor to the complex type contraints.
16279 */
16280 particle->children->children =
16281 (xmlSchemaTreeItemPtr) baseType->subtypes;
16282 }
16283 }
16284 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016285 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016286 /*
16287 * Apply the complex type component constraints; this will not
16288 * check attributes, since this is done in
16289 * xmlSchemaBuildAttributeValidation().
16290 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016291 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16292 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016293 /*
16294 * Inherit & check constraints for attributes.
16295 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016296 xmlSchemaBuildAttributeValidation(pctxt, type);
16297 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016298 /*
16299 * Simple Type Definition Schema Component
16300 */
16301 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016302 if (VARIETY_LIST(type)) {
16303 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016304 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016305 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016306 if (type->subtypes == NULL) {
16307 /*
16308 * This one is really needed, so get out.
16309 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016310 PERROR_INT("xmlSchemaTypeFixup",
16311 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016312 return;
16313 }
16314 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016315 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16316 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016317 /*
16318 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016319 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016320 if (type->memberTypes == NULL) {
16321 /*
16322 * This one is really needed, so get out.
16323 */
16324 return;
16325 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016326 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016327 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016328 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016329 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016330 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016331 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016332 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016333 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016334 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16335 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016336 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016337 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016338 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016339 */
16340 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016341 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016342 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016343 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16344 /*
16345 * Inherit the itemType.
16346 */
16347 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016348 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016349 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16350 /*
16351 * NOTE that we won't assign the memberTypes of the base,
16352 * since this will make trouble when freeing them; we will
16353 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016354 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016355 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016356 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016357 /*
16358 * Check constraints.
16359 *
16360 * TODO: Split this somehow, we need to know first if we can derive
16361 * from the base type at all!
16362 */
16363 if (type->baseType != NULL) {
16364 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016365 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016366 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016367 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016368 * applied beforehand.
16369 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016370 xmlSchemaCheckSRCSimpleType(pctxt, type);
16371 xmlSchemaCheckFacetValues(type, pctxt);
16372 if ((type->facetSet != NULL) ||
16373 (type->baseType->facetSet != NULL))
16374 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16375 /*
16376 * Whitespace value.
16377 */
16378 xmlSchemaTypeFixupWhitespace(type);
16379 xmlSchemaTypeFixupOptimFacets(type);
16380 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016381 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016382
Daniel Veillard8651f532002-04-17 09:06:27 +000016383#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016384 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016385 xmlGenericError(xmlGenericErrorContext,
16386 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016387 type->node->doc->URL,
16388 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016389 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016390 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016391 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016392 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16393 switch (type->contentType) {
16394 case XML_SCHEMA_CONTENT_SIMPLE:
16395 xmlGenericError(xmlGenericErrorContext, "simple\n");
16396 break;
16397 case XML_SCHEMA_CONTENT_ELEMENTS:
16398 xmlGenericError(xmlGenericErrorContext, "elements\n");
16399 break;
16400 case XML_SCHEMA_CONTENT_UNKNOWN:
16401 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16402 break;
16403 case XML_SCHEMA_CONTENT_EMPTY:
16404 xmlGenericError(xmlGenericErrorContext, "empty\n");
16405 break;
16406 case XML_SCHEMA_CONTENT_MIXED:
16407 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016408 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016409 xmlGenericError(xmlGenericErrorContext,
16410 "mixed as emptiable particle\n");
16411 else
16412 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16413 break;
16414 /* Removed, since not used. */
16415 /*
16416 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16417 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16418 break;
16419 */
16420 case XML_SCHEMA_CONTENT_BASIC:
16421 xmlGenericError(xmlGenericErrorContext, "basic\n");
16422 break;
16423 default:
16424 xmlGenericError(xmlGenericErrorContext,
16425 "not registered !!!\n");
16426 break;
16427 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016428 }
16429#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016430}
16431
16432/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016433 * xmlSchemaCheckFacet:
16434 * @facet: the facet
16435 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016436 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016437 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016438 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016439 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016440 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016441 * Returns 0 if valid, a positive error code if not valid and
16442 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016443 */
16444int
16445xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016446 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016447 xmlSchemaParserCtxtPtr pctxt,
16448 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016449{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016450 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016451
Daniel Veillardce682bc2004-11-05 17:22:25 +000016452 if ((facet == NULL) || (typeDecl == NULL))
16453 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016454 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016455 * TODO: will the parser context be given if used from
16456 * the relaxNG module?
16457 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016458 if (pctxt == NULL)
16459 ctxtGiven = 0;
16460 else
16461 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016462
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016463 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016464 case XML_SCHEMA_FACET_MININCLUSIVE:
16465 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16466 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016467 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16468 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016469 /*
16470 * Okay we need to validate the value
16471 * at that point.
16472 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016473 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016474
16475 /* 4.3.5.5 Constraints on enumeration Schema Components
16476 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016477 * It is an ·error· if any member of {value} is not in the
16478 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016479 *
16480 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016481 * The value ·must· be in the
16482 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016483 */
16484 /*
16485 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016486 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016487 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016488 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016489 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016490 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016491 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016492 */
16493 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16494 base = typeDecl->baseType;
16495 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016496 PERROR_INT("xmlSchemaCheckFacet",
16497 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016498 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016499 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016500 } else
16501 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016502
16503 if (! ctxtGiven) {
16504 /*
16505 * A context is needed if called from RelaxNG.
16506 */
16507 pctxt = xmlSchemaNewParserCtxt("*");
16508 if (pctxt == NULL)
16509 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016510 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016511 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016512 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016513 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016514 * facet->node is just the node holding the facet
16515 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016516 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016517 */
16518 ret = xmlSchemaVCheckCVCSimpleType(
16519 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16520 facet->value, &(facet->val), 1, 1, 0);
16521 if (ret != 0) {
16522 if (ret < 0) {
16523 /* No error message for RelaxNG. */
16524 if (ctxtGiven) {
16525 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16526 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16527 "Internal error: xmlSchemaCheckFacet, "
16528 "failed to validate the value '%s' of the "
16529 "facet '%s' against the base type",
16530 facet->value, xmlSchemaFacetTypeToString(facet->type));
16531 }
16532 goto internal_error;
16533 }
16534 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16535 /* No error message for RelaxNG. */
16536 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016537 xmlChar *str = NULL;
16538
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016539 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16540 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016541 "The value '%s' of the facet does not validate "
16542 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016543 facet->value,
16544 xmlSchemaFormatQName(&str,
16545 base->targetNamespace, base->name));
16546 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016547 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016548 goto exit;
16549 } else if (facet->val == NULL) {
16550 if (ctxtGiven) {
16551 PERROR_INT("xmlSchemaCheckFacet",
16552 "value was not computed");
16553 }
16554 TODO
16555 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016556 break;
16557 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016558 case XML_SCHEMA_FACET_PATTERN:
16559 facet->regexp = xmlRegexpCompile(facet->value);
16560 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016561 ret = XML_SCHEMAP_REGEXP_INVALID;
16562 /* No error message for RelaxNG. */
16563 if (ctxtGiven) {
16564 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16565 ret, facet->node, typeDecl,
16566 "The value '%s' of the facet 'pattern' is not a "
16567 "valid regular expression",
16568 facet->value, NULL);
16569 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016570 }
16571 break;
16572 case XML_SCHEMA_FACET_TOTALDIGITS:
16573 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16574 case XML_SCHEMA_FACET_LENGTH:
16575 case XML_SCHEMA_FACET_MAXLENGTH:
16576 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016577 ret = xmlSchemaValidatePredefinedType(
16578 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16579 facet->value, &(facet->val));
16580 if (ret != 0) {
16581 if (ret < 0) {
16582 /* No error message for RelaxNG. */
16583 if (ctxtGiven) {
16584 PERROR_INT("xmlSchemaCheckFacet",
16585 "validating facet value");
16586 }
16587 goto internal_error;
16588 }
16589 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16590 /* No error message for RelaxNG. */
16591 if (ctxtGiven) {
16592 /* error code */
16593 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16594 ret, facet->node, typeDecl,
16595 "The value '%s' of the facet '%s' is not a valid "
16596 "'nonNegativeInteger'",
16597 facet->value,
16598 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016599 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016600 }
16601 break;
16602 }
16603 case XML_SCHEMA_FACET_WHITESPACE:{
16604 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16605 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16606 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16607 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16608 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16609 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16610 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016611 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16612 /* No error message for RelaxNG. */
16613 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016614 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016615 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16616 ret, facet->node, typeDecl,
16617 "The value '%s' of the facet 'whitespace' is not "
16618 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016619 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016620 }
16621 }
16622 default:
16623 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016624 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016625exit:
16626 if ((! ctxtGiven) && (pctxt != NULL))
16627 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016628 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016629internal_error:
16630 if ((! ctxtGiven) && (pctxt != NULL))
16631 xmlSchemaFreeParserCtxt(pctxt);
16632 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016633}
16634
16635/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016636 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016637 * @typeDecl: the schema type definition
16638 * @ctxt: the schema parser context
16639 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016640 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016641 */
16642static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016643xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16644 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016645{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016646 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016647 /*
16648 * NOTE: It is intended to use the facets list, instead
16649 * of facetSet.
16650 */
16651 if (typeDecl->facets != NULL) {
16652 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016653
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016654 /*
16655 * Temporarily assign the "schema" to the validation context
16656 * of the parser context. This is needed for NOTATION validation.
16657 */
16658 if (ctxt->vctxt == NULL) {
16659 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16660 return;
16661 }
16662 ctxt->vctxt->schema = ctxt->schema;
16663
Daniel Veillard01fa6152004-06-29 17:04:39 +000016664 while (facet != NULL) {
16665 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16666 facet = facet->next;
16667 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016668
16669 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016670 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016671}
16672
16673/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016674 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016675 * @ctxtMGroup: the searched model group
16676 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016677 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016678 *
16679 * This one is intended to be used by
16680 * xmlSchemaCheckGroupDefCircular only.
16681 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016682 * Returns the particle with the circular model group definition reference,
16683 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016684 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016685static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016686xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016687 xmlSchemaTreeItemPtr particle)
16688{
16689 xmlSchemaTreeItemPtr circ = NULL;
16690 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016691 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016692
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016693 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016694 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016695 if (term == NULL)
16696 continue;
16697 switch (term->type) {
16698 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016699 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016700 if (gdef == groupDef)
16701 return (particle);
16702 /*
16703 * Mark this model group definition to avoid infinite
16704 * recursion on circular references not yet examined.
16705 */
16706 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16707 continue;
16708 if (gdef->children != NULL) {
16709 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16710 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16711 gdef->children->children);
16712 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16713 if (circ != NULL)
16714 return (circ);
16715 }
16716 break;
16717 case XML_SCHEMA_TYPE_SEQUENCE:
16718 case XML_SCHEMA_TYPE_CHOICE:
16719 case XML_SCHEMA_TYPE_ALL:
16720 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16721 if (circ != NULL)
16722 return (circ);
16723 break;
16724 default:
16725 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016726 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016727 }
16728 return (NULL);
16729}
16730
16731/**
16732 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016733 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016734 * @ctxt: the parser context
16735 * @name: the name
16736 *
16737 * Checks for circular references to model group definitions.
16738 */
16739static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016740xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016741 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016742 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016743{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016744 /*
16745 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016746 * 2 Circular groups are disallowed. That is, within the {particles}
16747 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016748 * is the group itself.
16749 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016750 if ((item == NULL) ||
16751 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16752 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016753 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016754 {
16755 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016756
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016757 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016758 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016759 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016760 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016761 * TODO: The error report is not adequate: this constraint
16762 * is defined for model groups but not definitions, but since
16763 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016764 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016765 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016766 */
16767 xmlSchemaPCustomErr(ctxt,
16768 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016769 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016770 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016771 "defined", xmlSchemaFormatQName(&str,
16772 item->targetNamespace, item->name));
16773 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016774 /*
16775 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016776 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016777 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016778 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016779 }
16780 }
16781}
16782
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016783/**
16784 * xmlSchemaGroupDefTermFixup:
16785 * @item: the particle with a model group definition as term
16786 * @ctxt: the parser context
16787 * @name: the name
16788 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016789 * Checks cos-all-limited.
16790 *
16791 * Assigns the model group of model group definitions to the "term"
16792 * of the referencing particle.
16793 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16794 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016795 */
16796static void
16797xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016798 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016799 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016800{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016801 if ((item == NULL) ||
16802 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16803 (item->children == NULL) ||
16804 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16805 (item->children->children == NULL))
16806 return;
16807 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016808 /*
16809 * TODO: Not nice, but we will anchor cos-all-limited here.
16810 */
16811 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16812 (item->maxOccurs != 1)) {
16813 /*
16814 * SPEC (1.2) "the {term} property of a particle with
16815 * {max occurs}=1which is part of a pair which constitutes the
16816 * {content type} of a complex type definition."
16817 */
16818 xmlSchemaPCustomErr(ctxt,
16819 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16820 NULL, (xmlSchemaTypePtr) item, item->node,
16821 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16822 "group is its term", NULL);
16823 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016824}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016825
16826/**
16827 * xmlSchemaGetCircAttrGrRef:
16828 * @ctxtGr: the searched attribute group
16829 * @attr: the current attribute list to be processed
16830 *
16831 * This one is intended to be used by
16832 * xmlSchemaCheckSRCAttributeGroupCircular only.
16833 *
16834 * Returns the circular attribute grou reference, otherwise NULL.
16835 */
16836static xmlSchemaAttributeGroupPtr
16837xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16838 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016839{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016840 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16841 int marked;
16842 /*
16843 * We will search for an attribute group reference which
16844 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016845 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016846 while (attr != NULL) {
16847 marked = 0;
16848 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16849 gr = (xmlSchemaAttributeGroupPtr) attr;
16850 if (gr->refItem != NULL) {
16851 if (gr->refItem == ctxtGr)
16852 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016853 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016854 XML_SCHEMAS_ATTRGROUP_MARKED) {
16855 attr = attr->next;
16856 continue;
16857 } else {
16858 /*
16859 * Mark as visited to avoid infinite recursion on
16860 * circular references not yet examined.
16861 */
16862 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16863 marked = 1;
16864 }
16865 }
16866 if (gr->attributes != NULL)
16867 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16868 /*
16869 * Unmark the visited group's attributes.
16870 */
16871 if (marked)
16872 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16873 if (circ != NULL)
16874 return (circ);
16875 }
16876 attr = attr->next;
16877 }
16878 return (NULL);
16879}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016880
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016881/**
16882 * xmlSchemaCheckSRCAttributeGroupCircular:
16883 * attrGr: the attribute group definition
16884 * @ctxt: the parser context
16885 * @name: the name
16886 *
16887 * Checks for circular references of attribute groups.
16888 */
16889static void
16890xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016891 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016892 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016893{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016894 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016895 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016896 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016897 * 3 Circular group reference is disallowed outside <redefine>.
16898 * That is, unless this element information item's parent is
16899 * <redefine>, then among the [children], if any, there must
16900 * not be an <attributeGroup> with ref [attribute] which resolves
16901 * to the component corresponding to this <attributeGroup>. Indirect
16902 * circularity is also ruled out. That is, when QName resolution
16903 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16904 * any <attributeGroup>s with a ref [attribute] among the [children],
16905 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016906 * which resolves to the component corresponding to this <attributeGroup>.
16907 */
16908 /*
16909 * Only global components can be referenced.
16910 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016911 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016912 (attrGr->attributes == NULL))
16913 return;
16914 else {
16915 xmlSchemaAttributeGroupPtr circ;
16916
16917 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16918 if (circ != NULL) {
16919 /*
16920 * TODO: Report the referenced attr group as QName.
16921 */
16922 xmlSchemaPCustomErr(ctxt,
16923 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16924 NULL, NULL, circ->node,
16925 "Circular reference to the attribute group '%s' "
16926 "defined", attrGr->name);
16927 /*
16928 * NOTE: We will cut the reference to avoid further
16929 * confusion of the processor.
16930 * BADSPEC: The spec should define how to process in this case.
16931 */
16932 circ->attributes = NULL;
16933 circ->refItem = NULL;
16934 }
16935 }
16936}
16937
16938/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016939 * xmlSchemaAttrGrpFixup:
16940 * @attrgrpDecl: the schema attribute definition
16941 * @ctxt: the schema parser context
16942 * @name: the attribute name
16943 *
16944 * Fixes finish doing the computations on the attributes definitions
16945 */
16946static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016947xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016948 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016949{
16950 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016951 name = attrgrp->name;
16952 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016953 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016954 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016955 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016956
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016957 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016958 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016959 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016960 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016961 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016962 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16963 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016964 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016965 return;
16966 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016967 attrgrp->refItem = ref;
16968 /*
16969 * Check for self reference!
16970 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016971 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016972 attrgrp->attributes = ref->attributes;
16973 attrgrp->attributeWildcard = ref->attributeWildcard;
16974 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016975}
16976
16977/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016978 * xmlSchemaAttrCheckValConstr:
16979 * @item: an schema attribute declaration/use
16980 * @ctxt: a schema parser context
16981 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016982 *
16983 *
16984 * Schema Component Constraint: Attribute Declaration Properties Correct
16985 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016986 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016987 *
16988 * Fixes finish doing the computations on the attributes definitions
16989 */
16990static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016991xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016992 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016993 const xmlChar * name ATTRIBUTE_UNUSED)
16994{
16995
16996 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016997 * 2 if there is a {value constraint}, the canonical lexical
16998 * representation of its value must be ·valid· with respect
16999 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017000 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017001 if (item->defValue != NULL) {
17002 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017003
17004 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017005 PERROR_INT("xmlSchemaCheckAttrValConstr",
17006 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017007 return;
17008 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017009 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17010 item->node, item->subtypes, item->defValue, &(item->defVal),
17011 1, 1, 0);
17012 if (ret != 0) {
17013 if (ret < 0) {
17014 PERROR_INT("xmlSchemaAttrCheckValConstr",
17015 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017016 return;
17017 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017018 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17019 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17020 ret, item->node, (xmlSchemaTypePtr) item,
17021 "The value of the value constraint is not valid", NULL, NULL);
17022 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017023 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017024 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017025}
17026
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017027static xmlSchemaElementPtr
17028xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17029 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017030{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017031 xmlSchemaElementPtr ret;
17032
17033 if (SUBST_GROUP_AFF(ancestor) == NULL)
17034 return (NULL);
17035 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17036 return (ancestor);
17037
17038 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17039 return (NULL);
17040 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17041 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17042 SUBST_GROUP_AFF(ancestor));
17043 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17044
17045 return (ret);
17046}
17047
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017048/**
17049 * xmlSchemaCheckElemPropsCorrect:
17050 * @ctxt: a schema parser context
17051 * @decl: the element declaration
17052 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017053 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017054 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017055 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017056 *
17057 * STATUS:
17058 * missing: (6)
17059 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017060static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017061xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17062 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017063{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017064 int ret = 0;
17065 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017066 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017067 * SPEC (1) "The values of the properties of an element declaration
17068 * must be as described in the property tableau in The Element
17069 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17070 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017071 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017072 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017073 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017074
17075 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017076 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017077 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017078 * affiliation}, then {scope} must be global."
17079 */
17080 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17081 xmlSchemaPCustomErr(pctxt,
17082 XML_SCHEMAP_E_PROPS_CORRECT_3,
17083 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17084 "Only global element declarations can have a "
17085 "substitution group affiliation", NULL);
17086 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017087 }
17088 /*
17089 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17090 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017091 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017092 * property."
17093 */
17094 if (head == elemDecl)
17095 circ = head;
17096 else if (SUBST_GROUP_AFF(head) != NULL)
17097 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17098 else
17099 circ = NULL;
17100 if (circ != NULL) {
17101 xmlChar *strA = NULL, *strB = NULL;
17102
17103 xmlSchemaPCustomErrExt(pctxt,
17104 XML_SCHEMAP_E_PROPS_CORRECT_6,
17105 NULL, (xmlSchemaTypePtr) circ, circ->node,
17106 "The element declaration '%s' defines a circular "
17107 "substitution group to element declaration '%s'",
17108 xmlSchemaGetComponentQName(&strA, circ),
17109 xmlSchemaGetComponentQName(&strB, head),
17110 NULL);
17111 FREE_AND_NULL(strA)
17112 FREE_AND_NULL(strB)
17113 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17114 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017115 /*
17116 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017117 * the {type definition}
17118 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017119 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017120 * of the {substitution group exclusions} of the {substitution group
17121 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17122 * (if the {type definition} is complex) or as defined in
17123 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017124 * simple)."
17125 *
17126 * NOTE: {substitution group exclusions} means the values of the
17127 * attribute "final".
17128 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017129
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017130 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017131 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017132
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017133 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17134 set |= SUBSET_EXTENSION;
17135 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17136 set |= SUBSET_RESTRICTION;
17137
17138 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17139 ELEM_TYPE(head), set) != 0) {
17140 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17141
17142 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017143 xmlSchemaPCustomErrExt(pctxt,
17144 XML_SCHEMAP_E_PROPS_CORRECT_4,
17145 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017146 "The type definition '%s' was "
17147 "either rejected by the substitution group "
17148 "affiliation '%s', or not validly derived from its type "
17149 "definition '%s'",
17150 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017151 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017152 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017153 FREE_AND_NULL(strA)
17154 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017155 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017156 }
17157 }
17158 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017159 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017160 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017161 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017162 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017163 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017164 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017165 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017166 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017167 ((IS_SIMPLE_TYPE(typeDef) &&
17168 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017169 (IS_COMPLEX_TYPE(typeDef) &&
17170 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017171 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17172 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017173
17174 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17175 xmlSchemaPCustomErr(pctxt,
17176 XML_SCHEMAP_E_PROPS_CORRECT_5,
17177 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17178 "The type definition (or type definition's content type) is or "
17179 "is derived from ID; value constraints are not allowed in "
17180 "conjunction with such a type definition", NULL);
17181 } else if (elemDecl->value != NULL) {
17182 int vcret;
17183 xmlNodePtr node = NULL;
17184
17185 /*
17186 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17187 * representation of its value must be ·valid· with respect to the
17188 * {type definition} as defined in Element Default Valid (Immediate)
17189 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017190 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017191 if (typeDef == NULL) {
17192 xmlSchemaPErr(pctxt, elemDecl->node,
17193 XML_SCHEMAP_INTERNAL,
17194 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17195 "type is missing... skipping validation of "
17196 "the value constraint", NULL, NULL);
17197 return (-1);
17198 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017199 if (elemDecl->node != NULL) {
17200 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17201 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17202 BAD_CAST "fixed");
17203 else
17204 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17205 BAD_CAST "default");
17206 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017207 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17208 typeDef, elemDecl->value, &(elemDecl->defVal));
17209 if (vcret != 0) {
17210 if (vcret < 0) {
17211 PERROR_INT("xmlSchemaElemCheckValConstr",
17212 "failed to validate the value constraint of an "
17213 "element declaration");
17214 return (-1);
17215 }
17216 return (vcret);
17217 }
17218 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017219
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017220 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017221}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017222
17223/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017224 * xmlSchemaCheckElemSubstGroup:
17225 * @ctxt: a schema parser context
17226 * @decl: the element declaration
17227 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017228 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017229 * Schema Component Constraint:
17230 * Substitution Group (cos-equiv-class)
17231 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017232 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017233 * a list will be built for each subst. group head, holding all direct
17234 * referents to this head.
17235 * NOTE that this function needs:
17236 * 1. circular subst. groups to be checked beforehand
17237 * 2. the declaration's type to be derived from the head's type
17238 *
17239 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017240 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017241 */
17242static void
17243xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17244 xmlSchemaElementPtr elemDecl)
17245{
17246 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17247 /* SPEC (1) "Its {abstract} is false." */
17248 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17249 return;
17250 {
17251 xmlSchemaElementPtr head;
17252 xmlSchemaTypePtr headType, type;
17253 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017254 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017255 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17256 * {disallowed substitutions} as the blocking constraint, as defined in
17257 * Substitution Group OK (Transitive) (§3.3.6)."
17258 */
17259 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17260 head = SUBST_GROUP_AFF(head)) {
17261 set = 0;
17262 methSet = 0;
17263 /*
17264 * The blocking constraints.
17265 */
17266 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17267 continue;
17268 headType = head->subtypes;
17269 type = elemDecl->subtypes;
17270 if (headType == type)
17271 goto add_member;
17272 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17273 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17274 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17275 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17276 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017277 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017278 * "The set of all {derivation method}s involved in the
17279 * derivation of D's {type definition} from C's {type definition}
17280 * does not intersect with the union of the blocking constraint,
17281 * C's {prohibited substitutions} (if C is complex, otherwise the
17282 * empty set) and the {prohibited substitutions} (respectively the
17283 * empty set) of any intermediate {type definition}s in the
17284 * derivation of D's {type definition} from C's {type definition}."
17285 */
17286 /*
17287 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17288 * subst.head axis, the methSet does not need to be computed for
17289 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017290 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017291 /*
17292 * The set of all {derivation method}s involved in the derivation
17293 */
17294 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017295 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017296 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17297 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17298 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017299
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017300 if ((type->flags &
17301 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17302 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17303 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17304
17305 type = type->baseType;
17306 }
17307 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017308 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017309 * the head's type.
17310 */
17311 type = elemDecl->subtypes->baseType;
17312 while (type != NULL) {
17313 if (IS_COMPLEX_TYPE(type)) {
17314 if ((type->flags &
17315 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17316 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17317 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17318 if ((type->flags &
17319 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17320 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17321 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17322 } else
17323 break;
17324 if (type == headType)
17325 break;
17326 type = type->baseType;
17327 }
17328 if ((set != 0) &&
17329 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17330 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17331 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17332 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17333 continue;
17334 }
17335add_member:
17336 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17337 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17338 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17339 }
17340 }
17341}
17342
17343/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017344 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017345 * @item: an schema element declaration/particle
17346 * @ctxt: a schema parser context
17347 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017348 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017349 * Validates the value constraints of an element declaration.
17350 *
17351 * Fixes finish doing the computations on the element declarations.
17352 */
17353static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017354xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017355 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017356 const xmlChar * name ATTRIBUTE_UNUSED)
17357{
17358 if (elemDecl == NULL)
17359 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017360 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17361 return;
17362 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017363 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17364 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017365}
17366
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017367/**
17368 * xmlSchemaMiscRefFixup:
17369 * @item: an schema component
17370 * @ctxt: a schema parser context
17371 * @name: the internal name of the component
17372 *
17373 * Resolves references of misc. schema components.
17374 */
17375static void
17376xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017377 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017378 const xmlChar * name ATTRIBUTE_UNUSED)
17379{
17380 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017381 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017382 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17383 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17384 xmlSchemaTreeItemPtr refItem;
17385 /*
17386 * Resolve the reference.
17387 */
17388 item->children = NULL;
17389 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17390 ref->itemType, ref->name, ref->targetNamespace);
17391 if (refItem == NULL) {
17392 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017393 NULL, GET_NODE(item), "ref", ref->name,
17394 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017395 } else {
17396 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17397 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017398 * NOTE that we will assign the model group definition
17399 * itself to the "term" of the particle. This will ease
17400 * the check for circular model group definitions. After
17401 * that the "term" will be assigned the model group of the
17402 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017403 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017404 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017405 } else
17406 item->children = refItem;
17407 }
17408 }
17409 }
17410}
17411
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017412static int
17413xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17414 xmlSchemaValPtr y)
17415{
17416 xmlSchemaTypePtr tx, ty, ptx, pty;
17417 int ret;
17418
17419 while (x != NULL) {
17420 /* Same types. */
17421 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17422 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17423 ptx = xmlSchemaGetPrimitiveType(tx);
17424 pty = xmlSchemaGetPrimitiveType(ty);
17425 /*
17426 * (1) if a datatype T' is ·derived· by ·restriction· from an
17427 * atomic datatype T then the ·value space· of T' is a subset of
17428 * the ·value space· of T. */
17429 /*
17430 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17431 * from a common atomic ancestor T then the ·value space·s of T'
17432 * and T'' may overlap.
17433 */
17434 if (ptx != pty)
17435 return(0);
17436 /*
17437 * We assume computed values to be normalized, so do a fast
17438 * string comparison for string based types.
17439 */
17440 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17441 IS_ANY_SIMPLE_TYPE(ptx)) {
17442 if (! xmlStrEqual(
17443 xmlSchemaValueGetAsString(x),
17444 xmlSchemaValueGetAsString(y)))
17445 return (0);
17446 } else {
17447 ret = xmlSchemaCompareValuesWhtsp(
17448 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17449 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17450 if (ret == -2)
17451 return(-1);
17452 if (ret != 0)
17453 return(0);
17454 }
17455 /*
17456 * Lists.
17457 */
17458 x = xmlSchemaValueGetNext(x);
17459 if (x != NULL) {
17460 y = xmlSchemaValueGetNext(y);
17461 if (y == NULL)
17462 return (0);
17463 } else if (xmlSchemaValueGetNext(y) != NULL)
17464 return (0);
17465 else
17466 return (1);
17467 }
17468 return (0);
17469}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017470
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017471/**
17472 * xmlSchemaAttrFixup:
17473 * @item: an schema attribute declaration/use.
17474 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017475 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017476 *
17477 * Fixes finish doing the computations on attribute declarations/uses.
17478 */
17479static void
17480xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017481 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017482 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017483{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017484 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017485 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017486 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017487 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017488 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017489 * The simple type definition corresponding to the <simpleType> element
17490 * information item in the [children], if present, otherwise the simple
17491 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017492 * [attribute], if present, otherwise the ·simple ur-type definition·.
17493 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017494 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017495 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017496 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17497 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017498 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017499 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017500 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017501
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017502 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17503 item->typeNs);
17504 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017505 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017506 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017507 (xmlSchemaTypePtr) item, item->node,
17508 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017509 XML_SCHEMA_TYPE_SIMPLE, NULL);
17510 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017511 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017512
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017513 } else if (item->ref != NULL) {
17514 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017515
Daniel Veillardc0826a72004-08-10 14:17:33 +000017516 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017517 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017518 * attribute declaration.
17519 */
17520 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017521 * TODO: Evaluate, what errors could occur if the declaration is not
17522 * found. It might be possible that the "typefixup" might crash if
17523 * no ref declaration was found.
17524 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017525 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017526 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017527 xmlSchemaPResCompAttrErr(ctxt,
17528 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017529 (xmlSchemaTypePtr) item, item->node,
17530 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017531 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017532 return;
17533 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017534 item->refDecl = decl;
17535 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017536 item->subtypes = decl->subtypes;
17537 /*
17538 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017539 * au-props-correct.2: If the {attribute declaration} has a fixed
17540 * {value constraint}, then if the attribute use itself has a
17541 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017542 * that of the {attribute declaration}'s {value constraint}.
17543 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017544 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017545 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017546 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017547 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017548 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17549 NULL, NULL, item->node,
17550 "The attribute declaration has a 'fixed' value constraint "
17551 ", thus it must be 'fixed' in attribute use as well",
17552 NULL);
17553 } else {
17554 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17555 xmlSchemaPCustomErr(ctxt,
17556 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17557 NULL, NULL, item->node,
17558 "The 'fixed' value constraint of the attribute use "
17559 "must match the attribute declaration's value "
17560 "constraint '%s'",
17561 decl->defValue);
17562 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017563 }
17564 /*
17565 * FUTURE: One should change the values of the attr. use
17566 * if ever validation should be attempted even if the
17567 * schema itself was not fully valid.
17568 */
17569 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017570 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017571 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17572 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017573}
17574
17575/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017576 * xmlSchemaResolveIDCKeyRef:
17577 * @idc: the identity-constraint definition
17578 * @ctxt: the schema parser context
17579 * @name: the attribute name
17580 *
17581 * Resolve keyRef references to key/unique IDCs.
17582 */
17583static void
17584xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017585 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017586 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017587{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017588 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17589 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017590 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017591 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017592 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017593 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017594 idc->ref->targetNamespace);
17595 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017596 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017597 * TODO: It is actually not an error to fail to resolve.
17598 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017599 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017600 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017601 (xmlSchemaTypePtr) idc, idc->node,
17602 "refer", idc->ref->name,
17603 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017604 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17605 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017606 } else {
17607 if (idc->nbFields !=
17608 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17609 xmlChar *str = NULL;
17610 xmlSchemaIDCPtr refer;
17611
17612 refer = (xmlSchemaIDCPtr) idc->ref->item;
17613 /*
17614 * SPEC c-props-correct(2)
17615 * "If the {identity-constraint category} is keyref,
17616 * the cardinality of the {fields} must equal that of
17617 * the {fields} of the {referenced key}.
17618 */
17619 xmlSchemaPCustomErr(pctxt,
17620 XML_SCHEMAP_C_PROPS_CORRECT,
17621 NULL, (xmlSchemaTypePtr) idc, idc->node,
17622 "The cardinality of the keyref differs from the "
17623 "cardinality of the referenced key '%s'",
17624 xmlSchemaFormatQName(&str, refer->targetNamespace,
17625 refer->name)
17626 );
17627 FREE_AND_NULL(str)
17628 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017629 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017630 }
17631}
17632
17633/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017634 * xmlSchemaParse:
17635 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017636 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017637 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017638 * XML Shema struture which can be used to validate instances.
17639 * *WARNING* this interface is highly subject to change
17640 *
17641 * Returns the internal XML Schema structure built from the resource or
17642 * NULL in case of error
17643 */
17644xmlSchemaPtr
17645xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17646{
17647 xmlSchemaPtr ret = NULL;
17648 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017649 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017650 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017651
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017652 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017653 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017654 * the API; i.e. not automatically by the validated instance document.
17655 */
17656
Daniel Veillard4255d502002-04-16 15:50:10 +000017657 xmlSchemaInitTypes();
17658
Daniel Veillard6045c902002-10-09 21:13:59 +000017659 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017660 return (NULL);
17661
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017662 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017663 ctxt->counter = 0;
17664 ctxt->container = NULL;
17665
17666 /*
17667 * First step is to parse the input document into an DOM/Infoset
17668 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017669 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017670 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017671 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017672 if (doc == NULL) {
17673 xmlSchemaPErr(ctxt, NULL,
17674 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017675 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017676 ctxt->URL, NULL);
17677 return (NULL);
17678 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017679 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017680 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17681 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017682 if (doc == NULL) {
17683 xmlSchemaPErr(ctxt, NULL,
17684 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017685 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017686 NULL, NULL);
17687 return (NULL);
17688 }
17689 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017690 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017691 } else if (ctxt->doc != NULL) {
17692 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017693 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017694 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017695 xmlSchemaPErr(ctxt, NULL,
17696 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017697 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017698 NULL, NULL);
17699 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017700 }
17701
17702 /*
17703 * Then extract the root and Schema parse it
17704 */
17705 root = xmlDocGetRootElement(doc);
17706 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017707 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17708 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017709 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017710 if (!preserve) {
17711 xmlFreeDoc(doc);
17712 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017713 return (NULL);
17714 }
17715
17716 /*
17717 * Remove all the blank text nodes
17718 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017719 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017720
17721 /*
17722 * Then do the parsing for good
17723 */
17724 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017725 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017726 if (!preserve) {
17727 xmlFreeDoc(doc);
17728 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017729 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017730 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017731 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017732 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017733 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017734 ctxt->ctxtType = NULL;
17735 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017736
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017737 /*
17738 * Resolve base types of simple/complex types.
17739 */
17740 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017741
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017742 if (ctxt->nberrors != 0)
17743 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017744
17745 if (ret->volatiles != NULL) {
17746 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17747 int i;
17748 xmlSchemaTreeItemPtr item;
17749
17750 for (i = 0; i < list->nbItems; i++) {
17751 item = (xmlSchemaTreeItemPtr) list->items[i];
17752 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17753 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017754 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017755 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017756 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017757 * Then fixup all attributes declarations
17758 */
17759 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017760 /*
17761 * Then fixup all attributes group declarations
17762 */
17763 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17764 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017765 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017766 * Resolve identity-constraint keyRefs.
17767 */
17768 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017769 /*
17770 * Check type defnitions for circular references.
17771 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017772 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017773 xmlSchemaCheckTypeDefCircular, ctxt);
17774 /*
17775 * Check model groups defnitions for circular references.
17776 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017777 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017778 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017779 /*
17780 * Set the "term" of particles pointing to model group definitions
17781 * to the contained model group.
17782 */
17783 if (ret->volatiles != NULL) {
17784 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17785 int i;
17786 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017787
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017788 for (i = 0; i < list->nbItems; i++) {
17789 item = (xmlSchemaParticlePtr) list->items[i];
17790 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17791 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17792 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017793 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017794 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017795 * Check attribute groups for circular references.
17796 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017797 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17798 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017799 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017800 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017801 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017802 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017803 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017804 /*
17805 * We will stop here if the schema was not valid to avoid internal errors
17806 * on missing sub-components. This is not conforming to the spec, since it
17807 * allows missing components, but it might make further processing crash.
17808 * So see it as a very strict handling, which might be made more lax in the
17809 * future.
17810 */
17811 if (ctxt->nberrors != 0)
17812 goto exit;
17813 /*
17814 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017815 */
17816 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017817 /*
17818 * Validate the value constraint of attribute declarations/uses.
17819 */
17820 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017821 /*
17822 * Validate the value constraint of element declarations.
17823 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017824 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017825
17826 if (ctxt->nberrors != 0)
17827 goto exit;
17828
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017829 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017830 * TODO: cos-element-consistent, cos-all-limited
17831 *
17832 * Then build the content model for all complex types
17833 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017834 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017835 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017836
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017837exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017838 if (ctxt->nberrors != 0) {
17839 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017840 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017841 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017842 return (ret);
17843}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017844
Daniel Veillard4255d502002-04-16 15:50:10 +000017845/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017846 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017847 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017848 * @err: the error callback
17849 * @warn: the warning callback
17850 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017851 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017852 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017853 */
17854void
17855xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017856 xmlSchemaValidityErrorFunc err,
17857 xmlSchemaValidityWarningFunc warn, void *ctx)
17858{
Daniel Veillard4255d502002-04-16 15:50:10 +000017859 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017860 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017861 ctxt->error = err;
17862 ctxt->warning = warn;
17863 ctxt->userData = ctx;
17864}
17865
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017866/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017867 * xmlSchemaGetParserErrors:
17868 * @ctxt: a XMl-Schema parser context
17869 * @err: the error callback result
17870 * @warn: the warning callback result
17871 * @ctx: contextual data for the callbacks result
17872 *
17873 * Get the callback information used to handle errors for a parser context
17874 *
17875 * Returns -1 in case of failure, 0 otherwise
17876 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017877int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017878xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17879 xmlSchemaValidityErrorFunc * err,
17880 xmlSchemaValidityWarningFunc * warn, void **ctx)
17881{
17882 if (ctxt == NULL)
17883 return(-1);
17884 if (err != NULL)
17885 *err = ctxt->error;
17886 if (warn != NULL)
17887 *warn = ctxt->warning;
17888 if (ctx != NULL)
17889 *ctx = ctxt->userData;
17890 return(0);
17891}
17892
17893/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017894 * xmlSchemaFacetTypeToString:
17895 * @type: the facet type
17896 *
17897 * Convert the xmlSchemaTypeType to a char string.
17898 *
17899 * Returns the char string representation of the facet type if the
17900 * type is a facet and an "Internal Error" string otherwise.
17901 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017902static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017903xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17904{
17905 switch (type) {
17906 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017907 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017908 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017909 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017910 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017911 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017912 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017913 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017914 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017915 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017916 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017917 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017918 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017919 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017920 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017921 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017922 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017923 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017924 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017925 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017926 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017927 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017928 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017929 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017930 default:
17931 break;
17932 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017933 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017934}
17935
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017936static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017937xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17938{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017939 /*
17940 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017941 * from xsd:string.
17942 */
17943 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017944 /*
17945 * Note that we assume a whitespace of preserve for anySimpleType.
17946 */
17947 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17948 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17949 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017950 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017951 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017952 else {
17953 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017954 * For all ·atomic· datatypes other than string (and types ·derived·
17955 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000017956 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017957 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017958 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017959 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017960 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017961 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017962 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017963 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017964 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017965 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
17966 } else if (VARIETY_UNION(type)) {
17967 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
17968 } else if (VARIETY_ATOMIC(type)) {
17969 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
17970 return (XML_SCHEMA_WHITESPACE_PRESERVE);
17971 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
17972 return (XML_SCHEMA_WHITESPACE_REPLACE);
17973 else
17974 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017975 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017976 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017977}
17978
Daniel Veillard4255d502002-04-16 15:50:10 +000017979/************************************************************************
17980 * *
17981 * Simple type validation *
17982 * *
17983 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017984
Daniel Veillard4255d502002-04-16 15:50:10 +000017985
17986/************************************************************************
17987 * *
17988 * DOM Validation code *
17989 * *
17990 ************************************************************************/
17991
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017992static void
17993xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
17994{
17995 int i, nbItems;
17996 xmlSchemaTypePtr item, *items;
17997
17998
17999 /*
18000 * During the Assemble of the schema ctxt->curItems has
18001 * been filled with the relevant new items. Fix those up.
18002 */
18003 nbItems = ctxt->assemble->nbItems;
18004 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018005
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018006 for (i = 0; i < nbItems; i++) {
18007 item = items[i];
18008 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018009 case XML_SCHEMA_TYPE_COMPLEX:
18010 case XML_SCHEMA_TYPE_SIMPLE:
18011 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18012 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018013 case XML_SCHEMA_TYPE_ATTRIBUTE:
18014 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18015 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018016 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018017 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018018 ctxt, NULL);
18019 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018020 case XML_SCHEMA_TYPE_PARTICLE:
18021 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018022 break;
18023 case XML_SCHEMA_TYPE_IDC_KEY:
18024 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18025 case XML_SCHEMA_TYPE_IDC_KEYREF:
18026 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18027 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018028 default:
18029 break;
18030 }
18031 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018032 if (ctxt->nberrors != 0)
18033 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018034 /*
18035 * Circularity checks.
18036 */
18037 for (i = 0; i < nbItems; i++) {
18038 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018039 switch (item->type) {
18040 case XML_SCHEMA_TYPE_COMPLEX:
18041 case XML_SCHEMA_TYPE_SIMPLE:
18042 xmlSchemaCheckTypeDefCircular(
18043 (xmlSchemaTypePtr) item, ctxt, NULL);
18044 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018045 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018046 xmlSchemaCheckGroupDefCircular(
18047 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018048 break;
18049 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18050 xmlSchemaCheckAttributeGroupCircular(
18051 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18052 break;
18053 default:
18054 break;
18055 }
18056 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018057 if (ctxt->nberrors != 0)
18058 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018059 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018060 * Set the "term" of particles pointing to model group definitions
18061 * to the contained model group.
18062 */
18063 for (i = 0; i < nbItems; i++) {
18064 item = items[i];
18065 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18066 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018067 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018068 XML_SCHEMA_TYPE_GROUP)) {
18069 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18070 ctxt, NULL);
18071 }
18072 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018073 if (ctxt->nberrors != 0)
18074 return;
18075 for (i = 0; i < nbItems; i++) {
18076 item = items[i];
18077 switch (item->type) {
18078 case XML_SCHEMA_TYPE_ELEMENT:
18079 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18080 NULL, NULL, NULL);
18081 break;
18082 default:
18083 break;
18084 }
18085 }
18086 if (ctxt->nberrors != 0)
18087 return;
18088
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018089 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018090 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018091 */
18092 for (i = 0; i < nbItems; i++) {
18093 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018094 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018095 case XML_SCHEMA_TYPE_SIMPLE:
18096 case XML_SCHEMA_TYPE_COMPLEX:
18097 xmlSchemaTypeFixup(item, ctxt, NULL);
18098 break;
18099 default:
18100 break;
18101 }
18102 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018103 if (ctxt->nberrors != 0)
18104 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018105 /*
18106 * Validate value contraint values.
18107 */
18108 for (i = 0; i < nbItems; i++) {
18109 item = items[i];
18110 switch (item->type) {
18111 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018112 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18113 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018114 break;
18115 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018116 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018117 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018118 break;
18119 default:
18120 break;
18121 }
18122 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018123 if (ctxt->nberrors != 0)
18124 return;
18125 /*
18126 * Build the content model for complex types.
18127 */
18128 for (i = 0; i < nbItems; i++) {
18129 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018130 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018131 case XML_SCHEMA_TYPE_COMPLEX:
18132 xmlSchemaBuildContentModel(item, ctxt, NULL);
18133 break;
18134 default:
18135 break;
18136 }
18137 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018138}
18139
18140/**
18141 * xmlSchemaAssembleByLocation:
18142 * @pctxt: a schema parser context
18143 * @vctxt: a schema validation context
18144 * @schema: the existing schema
18145 * @node: the node that fired the assembling
18146 * @nsName: the namespace name of the new schema
18147 * @location: the location of the schema
18148 *
18149 * Expands an existing schema by an additional schema.
18150 *
18151 * Returns 0 if the new schema is correct, a positive error code
18152 * number otherwise and -1 in case of an internal or API error.
18153 */
18154static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018155xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018156 xmlSchemaPtr schema,
18157 xmlNodePtr node,
18158 const xmlChar *nsName,
18159 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018160{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018161 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018162 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018163 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018164 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018165 xmlSchemaParserCtxtPtr pctxt;
18166
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018167 /*
18168 * This should be used:
18169 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018170 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018171 * 3. if requested via the API
18172 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018173 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018174 return (-1);
18175 /*
18176 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018177 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018178 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018179 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18180 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018181 pctxt = vctxt->pctxt;
18182 /*
18183 * Set the counter to produce unique names for anonymous items.
18184 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018185 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018186 /*
18187 * Acquire the schema document.
18188 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018189 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18190 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018191 if (ret != 0) {
18192 if (doc != NULL)
18193 xmlFreeDoc(doc);
18194 } else if (doc != NULL) {
18195 docElem = xmlDocGetRootElement(doc);
18196 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018197 * Create new assemble info.
18198 */
18199 if (pctxt->assemble == NULL) {
18200 pctxt->assemble = xmlSchemaNewAssemble();
18201 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018202 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018203 "Memory error: xmlSchemaAssembleByLocation, "
18204 "allocating assemble info", NULL);
18205 xmlFreeDoc(doc);
18206 return (-1);
18207 }
18208 }
18209 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018210 * Save and reset the context & schema.
18211 */
18212 oldflags = schema->flags;
18213 oldtns = schema->targetNamespace;
18214 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018215 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018216
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018217 xmlSchemaClearSchemaDefaults(schema);
18218 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018219 if ((targetNs != NULL) &&
18220 xmlStrEqual(targetNs, xmlSchemaNs)) {
18221 /*
18222 * We are parsing the schema for schema!
18223 */
18224 vctxt->pctxt->isS4S = 1;
18225 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018226 /* schema->nbCurItems = 0; */
18227 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018228 pctxt->ctxtType = NULL;
18229 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018230
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018231 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18232 if (pctxt->nberrors != 0) {
18233 vctxt->nberrors += pctxt->nberrors;
18234 goto finally;
18235 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018236 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018237 if (pctxt->nberrors != 0) {
18238 vctxt->nberrors += pctxt->nberrors;
18239 goto finally;
18240 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018241 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018242 if (pctxt->nberrors != 0)
18243 vctxt->nberrors += pctxt->nberrors;
18244finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018245 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018246 * Set the counter of items.
18247 */
18248 schema->counter = pctxt->counter;
18249 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018250 * Free the list of assembled components.
18251 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018252 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018253 /*
18254 * Restore the context & schema.
18255 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018256 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018257 schema->flags = oldflags;
18258 schema->targetNamespace = oldtns;
18259 schema->doc = olddoc;
18260 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018261 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018262 return (ret);
18263}
18264
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018265static xmlSchemaAttrInfoPtr
18266xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18267 int metaType)
18268{
18269 if (vctxt->nbAttrInfos == 0)
18270 return (NULL);
18271 {
18272 int i;
18273 xmlSchemaAttrInfoPtr iattr;
18274
18275 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18276 iattr = vctxt->attrInfos[i];
18277 if (iattr->metaType == metaType)
18278 return (iattr);
18279 }
18280
18281 }
18282 return (NULL);
18283}
18284
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018285/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018286 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018287 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018288 *
18289 * Expands an existing schema by an additional schema using
18290 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18291 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18292 * must be set to 1.
18293 *
18294 * Returns 0 if the new schema is correct, a positive error code
18295 * number otherwise and -1 in case of an internal or API error.
18296 */
18297static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018298xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018299{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018300 const xmlChar *cur, *end;
18301 const xmlChar *nsname = NULL, *location;
18302 int count = 0;
18303 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018304 xmlSchemaAttrInfoPtr iattr;
18305
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018306 /*
18307 * Parse the value; we will assume an even number of values
18308 * to be given (this is how Xerces and XSV work).
18309 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018310 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18311 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18312 if (iattr == NULL)
18313 xmlSchemaGetMetaAttrInfo(vctxt,
18314 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18315 if (iattr == NULL)
18316 return (0);
18317 cur = iattr->value;
18318 do {
18319 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018320 /*
18321 * Get the namespace name.
18322 */
18323 while (IS_BLANK_CH(*cur))
18324 cur++;
18325 end = cur;
18326 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18327 end++;
18328 if (end == cur)
18329 break;
18330 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018331 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018332 cur = end;
18333 }
18334 /*
18335 * Get the URI.
18336 */
18337 while (IS_BLANK_CH(*cur))
18338 cur++;
18339 end = cur;
18340 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18341 end++;
18342 if (end == cur)
18343 break;
18344 count++;
18345 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018346 cur = end;
18347 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18348 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018349 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018350 VERROR_INT("xmlSchemaAssembleByXSI",
18351 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018352 return (-1);
18353 }
18354 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018355 return (ret);
18356}
18357
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018358#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018359
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018360static const xmlChar *
18361xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18362 const xmlChar *prefix)
18363{
18364 if (vctxt->sax != NULL) {
18365 int i, j;
18366 xmlSchemaNodeInfoPtr inode;
18367
18368 for (i = vctxt->depth; i >= 0; i--) {
18369 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18370 inode = vctxt->elemInfos[i];
18371 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18372 if (((prefix == NULL) &&
18373 (inode->nsBindings[j] == NULL)) ||
18374 ((prefix != NULL) && xmlStrEqual(prefix,
18375 inode->nsBindings[j]))) {
18376
18377 /*
18378 * Note that the namespace bindings are already
18379 * in a string dict.
18380 */
18381 return (inode->nsBindings[j+1]);
18382 }
18383 }
18384 }
18385 }
18386 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018387#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018388 } else if (vctxt->reader != NULL) {
18389 xmlChar *nsName;
18390
18391 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18392 if (nsName != NULL) {
18393 const xmlChar *ret;
18394
18395 VAL_CREATE_DICT;
18396 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18397 xmlFree(nsName);
18398 return (ret);
18399 } else
18400 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018401#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018402 } else {
18403 xmlNsPtr ns;
18404
18405 if ((vctxt->inode->node == NULL) ||
18406 (vctxt->inode->node->doc == NULL)) {
18407 VERROR_INT("xmlSchemaLookupNamespace",
18408 "no node or node's doc avaliable");
18409 return (NULL);
18410 }
18411 ns = xmlSearchNs(vctxt->inode->node->doc,
18412 vctxt->inode->node, prefix);
18413 if (ns != NULL)
18414 return (ns->href);
18415 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018416 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018417}
18418
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018419/*
18420* This one works on the schema of the validation context.
18421*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018422static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018423xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18424 xmlSchemaPtr schema,
18425 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018426 const xmlChar *value,
18427 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018428 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018429{
18430 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018431
18432 if (vctxt && (vctxt->schema == NULL)) {
18433 VERROR_INT("xmlSchemaValidateNotation",
18434 "a schema is needed on the validation context");
18435 return (-1);
18436 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018437 ret = xmlValidateQName(value, 1);
18438 if (ret != 0)
18439 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018440 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018441 xmlChar *localName = NULL;
18442 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018443
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018444 localName = xmlSplitQName2(value, &prefix);
18445 if (prefix != NULL) {
18446 const xmlChar *nsName = NULL;
18447
18448 if (vctxt != NULL)
18449 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18450 else if (node != NULL) {
18451 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18452 if (ns != NULL)
18453 nsName = ns->href;
18454 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018455 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018456 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018457 return (1);
18458 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018459 if (nsName == NULL) {
18460 xmlFree(prefix);
18461 xmlFree(localName);
18462 return (1);
18463 }
18464 if (xmlHashLookup2(schema->notaDecl, localName,
18465 nsName) != NULL) {
18466 if (valNeeded && (val != NULL)) {
18467 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18468 BAD_CAST xmlStrdup(nsName));
18469 if (*val == NULL)
18470 ret = -1;
18471 }
18472 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018473 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018474 xmlFree(prefix);
18475 xmlFree(localName);
18476 } else {
18477 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18478 if (valNeeded && (val != NULL)) {
18479 (*val) = xmlSchemaNewNOTATIONValue(
18480 BAD_CAST xmlStrdup(value), NULL);
18481 if (*val == NULL)
18482 ret = -1;
18483 }
18484 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018485 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018486 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018487 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018488 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018489}
18490
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018491/************************************************************************
18492 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018493 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018494 * *
18495 ************************************************************************/
18496
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018497/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018498 * xmlSchemaAugmentIDC:
18499 * @idcDef: the IDC definition
18500 *
18501 * Creates an augmented IDC definition item.
18502 *
18503 * Returns the item, or NULL on internal errors.
18504 */
18505static void
18506xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18507 xmlSchemaValidCtxtPtr vctxt)
18508{
18509 xmlSchemaIDCAugPtr aidc;
18510
18511 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18512 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018513 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018514 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18515 NULL);
18516 return;
18517 }
18518 aidc->bubbleDepth = -1;
18519 aidc->def = idcDef;
18520 aidc->next = NULL;
18521 if (vctxt->aidcs == NULL)
18522 vctxt->aidcs = aidc;
18523 else {
18524 aidc->next = vctxt->aidcs;
18525 vctxt->aidcs = aidc;
18526 }
18527}
18528
18529/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018530 * xmlSchemaIDCNewBinding:
18531 * @idcDef: the IDC definition of this binding
18532 *
18533 * Creates a new IDC binding.
18534 *
18535 * Returns the new binding in case of succeeded, NULL on internal errors.
18536 */
18537static xmlSchemaPSVIIDCBindingPtr
18538xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18539{
18540 xmlSchemaPSVIIDCBindingPtr ret;
18541
18542 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18543 sizeof(xmlSchemaPSVIIDCBinding));
18544 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018545 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018546 "allocating a PSVI IDC binding item", NULL);
18547 return (NULL);
18548 }
18549 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18550 ret->definition = idcDef;
18551 return (ret);
18552}
18553
18554/**
18555 * xmlSchemaIDCStoreNodeTableItem:
18556 * @vctxt: the WXS validation context
18557 * @item: the IDC node table item
18558 *
18559 * The validation context is used to store an IDC node table items.
18560 * They are stored to avoid copying them if IDC node-tables are merged
18561 * with corresponding parent IDC node-tables (bubbling).
18562 *
18563 * Returns 0 if succeeded, -1 on internal errors.
18564 */
18565static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018566xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018567 xmlSchemaPSVIIDCNodePtr item)
18568{
18569 /*
18570 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018571 */
18572 if (vctxt->idcNodes == NULL) {
18573 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018574 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18575 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018576 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018577 "allocating the IDC node table item list", NULL);
18578 return (-1);
18579 }
18580 vctxt->sizeIdcNodes = 20;
18581 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18582 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018583 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18584 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018585 sizeof(xmlSchemaPSVIIDCNodePtr));
18586 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018587 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018588 "re-allocating the IDC node table item list", NULL);
18589 return (-1);
18590 }
18591 }
18592 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018593
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018594 return (0);
18595}
18596
18597/**
18598 * xmlSchemaIDCStoreKey:
18599 * @vctxt: the WXS validation context
18600 * @item: the IDC key
18601 *
18602 * The validation context is used to store an IDC key.
18603 *
18604 * Returns 0 if succeeded, -1 on internal errors.
18605 */
18606static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018607xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018608 xmlSchemaPSVIIDCKeyPtr key)
18609{
18610 /*
18611 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018612 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018613 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018614 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018615 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18616 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018617 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018618 "allocating the IDC key storage list", NULL);
18619 return (-1);
18620 }
18621 vctxt->sizeIdcKeys = 40;
18622 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18623 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018624 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18625 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018626 sizeof(xmlSchemaPSVIIDCKeyPtr));
18627 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018628 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018629 "re-allocating the IDC key storage list", NULL);
18630 return (-1);
18631 }
18632 }
18633 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018634
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018635 return (0);
18636}
18637
18638/**
18639 * xmlSchemaIDCAppendNodeTableItem:
18640 * @bind: the IDC binding
18641 * @ntItem: the node-table item
18642 *
18643 * Appends the IDC node-table item to the binding.
18644 *
18645 * Returns 0 on success and -1 on internal errors.
18646 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018647static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018648xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18649 xmlSchemaPSVIIDCNodePtr ntItem)
18650{
18651 if (bind->nodeTable == NULL) {
18652 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018653 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018654 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18655 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018656 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018657 "allocating an array of IDC node-table items", NULL);
18658 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018659 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018660 } else if (bind->sizeNodes <= bind->nbNodes) {
18661 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018662 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18663 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018664 sizeof(xmlSchemaPSVIIDCNodePtr));
18665 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018666 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018667 "re-allocating an array of IDC node-table items", NULL);
18668 return(-1);
18669 }
18670 }
18671 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018672 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018673}
18674
18675/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018676 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018677 * @vctxt: the WXS validation context
18678 * @matcher: the IDC matcher
18679 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018680 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018681 * of the given matcher. If none found, a new one is created
18682 * and added to the IDC table.
18683 *
18684 * Returns an IDC binding or NULL on internal errors.
18685 */
18686static xmlSchemaPSVIIDCBindingPtr
18687xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18688 xmlSchemaIDCMatcherPtr matcher)
18689{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018690 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018691
18692 info = vctxt->elemInfos[matcher->depth];
18693
18694 if (info->idcTable == NULL) {
18695 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18696 if (info->idcTable == NULL)
18697 return (NULL);
18698 return(info->idcTable);
18699 } else {
18700 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018701
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018702 bind = info->idcTable;
18703 do {
18704 if (bind->definition == matcher->aidc->def)
18705 return(bind);
18706 if (bind->next == NULL) {
18707 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18708 if (bind->next == NULL)
18709 return (NULL);
18710 return(bind->next);
18711 }
18712 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018713 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018714 }
18715 return (NULL);
18716}
18717
18718/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018719 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018720 * @key: the IDC key
18721 *
18722 * Frees an IDC key together with its compiled value.
18723 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018724static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018725xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18726{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018727 if (key->val != NULL)
18728 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018729 xmlFree(key);
18730}
18731
18732/**
18733 * xmlSchemaIDCFreeBinding:
18734 *
18735 * Frees an IDC binding. Note that the node table-items
18736 * are not freed.
18737 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018738static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018739xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18740{
18741 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018742 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18743 int i;
18744 /*
18745 * Node-table items for keyrefs are not stored globally
18746 * to the validation context, since they are not bubbled.
18747 * We need to free them here.
18748 */
18749 for (i = 0; i < bind->nbNodes; i++) {
18750 xmlFree(bind->nodeTable[i]->keys);
18751 xmlFree(bind->nodeTable[i]);
18752 }
18753 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018754 xmlFree(bind->nodeTable);
18755 }
18756 xmlFree(bind);
18757}
18758
18759/**
18760 * xmlSchemaIDCFreeIDCTable:
18761 * @bind: the first IDC binding in the list
18762 *
18763 * Frees an IDC table, i.e. all the IDC bindings in the list.
18764 */
18765static void
18766xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18767{
18768 xmlSchemaPSVIIDCBindingPtr prev;
18769
18770 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018771 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018772 bind = bind->next;
18773 xmlSchemaIDCFreeBinding(prev);
18774 }
18775}
18776
18777/**
18778 * xmlSchemaIDCFreeMatcherList:
18779 * @matcher: the first IDC matcher in the list
18780 *
18781 * Frees a list of IDC matchers.
18782 */
18783static void
18784xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18785{
18786 xmlSchemaIDCMatcherPtr next;
18787
18788 while (matcher != NULL) {
18789 next = matcher->next;
18790 if (matcher->keySeqs != NULL) {
18791 int i;
18792 for (i = 0; i < matcher->sizeKeySeqs; i++)
18793 if (matcher->keySeqs[i] != NULL)
18794 xmlFree(matcher->keySeqs[i]);
18795 xmlFree(matcher->keySeqs);
18796 }
18797 xmlFree(matcher);
18798 matcher = next;
18799 }
18800}
18801
18802/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018803 * xmlSchemaIDCAddStateObject:
18804 * @vctxt: the WXS validation context
18805 * @matcher: the IDC matcher
18806 * @sel: the XPath information
18807 * @parent: the parent "selector" state object if any
18808 * @type: "selector" or "field"
18809 *
18810 * Creates/reuses and activates state objects for the given
18811 * XPath information; if the XPath expression consists of unions,
18812 * multiple state objects are created for every unioned expression.
18813 *
18814 * Returns 0 on success and -1 on internal errors.
18815 */
18816static int
18817xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18818 xmlSchemaIDCMatcherPtr matcher,
18819 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018820 int type)
18821{
18822 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018823
18824 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018825 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018826 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018827 if (vctxt->xpathStatePool != NULL) {
18828 sto = vctxt->xpathStatePool;
18829 vctxt->xpathStatePool = sto->next;
18830 sto->next = NULL;
18831 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018832 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018833 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018834 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018835 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18836 if (sto == NULL) {
18837 xmlSchemaVErrMemory(NULL,
18838 "allocating an IDC state object", NULL);
18839 return (-1);
18840 }
18841 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18842 }
18843 /*
18844 * Add to global list.
18845 */
18846 if (vctxt->xpathStates != NULL)
18847 sto->next = vctxt->xpathStates;
18848 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018849
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018850 /*
18851 * Free the old xpath validation context.
18852 */
18853 if (sto->xpathCtxt != NULL)
18854 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18855
18856 /*
18857 * Create a new XPath (pattern) validation context.
18858 */
18859 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18860 (xmlPatternPtr) sel->xpathComp);
18861 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018862 VERROR_INT("xmlSchemaIDCAddStateObject",
18863 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018864 return (-1);
18865 }
18866 sto->type = type;
18867 sto->depth = vctxt->depth;
18868 sto->matcher = matcher;
18869 sto->sel = sel;
18870 sto->nbHistory = 0;
18871
18872#if DEBUG_IDC
18873 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18874 sto->sel->xpath);
18875#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018876 return (0);
18877}
18878
18879/**
18880 * xmlSchemaXPathEvaluate:
18881 * @vctxt: the WXS validation context
18882 * @nodeType: the nodeType of the current node
18883 *
18884 * Evaluates all active XPath state objects.
18885 *
18886 * Returns the number of IC "field" state objects which resolved to
18887 * this node, 0 if none resolved and -1 on internal errors.
18888 */
18889static int
18890xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018891 xmlElementType nodeType)
18892{
18893 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018894 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018895
18896 if (vctxt->xpathStates == NULL)
18897 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018898
18899 if (nodeType == XML_ATTRIBUTE_NODE)
18900 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018901#if DEBUG_IDC
18902 {
18903 xmlChar *str = NULL;
18904 xmlGenericError(xmlGenericErrorContext,
18905 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018906 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18907 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018908 FREE_AND_NULL(str)
18909 }
18910#endif
18911 /*
18912 * Process all active XPath state objects.
18913 */
18914 first = vctxt->xpathStates;
18915 sto = first;
18916 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018917#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018918 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018919 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18920 sto->matcher->aidc->def->name, sto->sel->xpath);
18921 else
18922 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18923 sto->matcher->aidc->def->name, sto->sel->xpath);
18924#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018925 if (nodeType == XML_ELEMENT_NODE)
18926 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018927 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018928 else
18929 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018930 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018931
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018932 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018933 VERROR_INT("xmlSchemaXPathEvaluate",
18934 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018935 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018936 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018937 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018938 goto next_sto;
18939 /*
18940 * Full match.
18941 */
18942#if DEBUG_IDC
18943 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018944 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018945#endif
18946 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018947 * Register a match in the state object history.
18948 */
18949 if (sto->history == NULL) {
18950 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18951 if (sto->history == NULL) {
18952 xmlSchemaVErrMemory(NULL,
18953 "allocating the state object history", NULL);
18954 return(-1);
18955 }
18956 sto->sizeHistory = 10;
18957 } else if (sto->sizeHistory <= sto->nbHistory) {
18958 sto->sizeHistory *= 2;
18959 sto->history = (int *) xmlRealloc(sto->history,
18960 sto->sizeHistory * sizeof(int));
18961 if (sto->history == NULL) {
18962 xmlSchemaVErrMemory(NULL,
18963 "re-allocating the state object history", NULL);
18964 return(-1);
18965 }
18966 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018967 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018968
18969#ifdef DEBUG_IDC
18970 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
18971 vctxt->depth);
18972#endif
18973
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018974 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
18975 xmlSchemaIDCSelectPtr sel;
18976 /*
18977 * Activate state objects for the IDC fields of
18978 * the IDC selector.
18979 */
18980#if DEBUG_IDC
18981 xmlGenericError(xmlGenericErrorContext, "IDC: "
18982 "activating field states\n");
18983#endif
18984 sel = sto->matcher->aidc->def->fields;
18985 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018986 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
18987 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
18988 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018989 sel = sel->next;
18990 }
18991 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
18992 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018993 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018994 */
18995#if DEBUG_IDC
18996 xmlGenericError(xmlGenericErrorContext,
18997 "IDC: key found\n");
18998#endif
18999 /*
19000 * Notify that the character value of this node is
19001 * needed.
19002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019003 if (resolved == 0) {
19004 if ((vctxt->inode->flags &
19005 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19006 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19007 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019008 resolved++;
19009 }
19010next_sto:
19011 if (sto->next == NULL) {
19012 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019013 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019014 */
19015 head = first;
19016 sto = vctxt->xpathStates;
19017 } else
19018 sto = sto->next;
19019 }
19020 return (resolved);
19021}
19022
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019023static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019024xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019025 xmlChar **buf,
19026 xmlSchemaPSVIIDCKeyPtr *seq,
19027 int count)
19028{
19029 int i, res;
19030 const xmlChar *value = NULL;
19031
19032 *buf = xmlStrdup(BAD_CAST "[");
19033 for (i = 0; i < count; i++) {
19034 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019035 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19036 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019037 if (res == 0)
19038 *buf = xmlStrcat(*buf, value);
19039 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019040 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19041 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019042 *buf = xmlStrcat(*buf, BAD_CAST "???");
19043 }
19044 if (i < count -1)
19045 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19046 else
19047 *buf = xmlStrcat(*buf, BAD_CAST "'");
19048 if (value != NULL) {
19049 xmlFree((xmlChar *) value);
19050 value = NULL;
19051 }
19052 }
19053 *buf = xmlStrcat(*buf, BAD_CAST "]");
19054
19055 return (BAD_CAST *buf);
19056}
19057
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019058/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019059 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019060 * @vctxt: the WXS validation context
19061 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019062 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019063 *
19064 * Processes and pops the history items of the IDC state objects.
19065 * IDC key-sequences are validated/created on IDC bindings.
19066 *
19067 * Returns 0 on success and -1 on internal errors.
19068 */
19069static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019070xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019071 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019072{
19073 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019074 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019075 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019076 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019077
19078 if (vctxt->xpathStates == NULL)
19079 return (0);
19080 sto = vctxt->xpathStates;
19081
19082#if DEBUG_IDC
19083 {
19084 xmlChar *str = NULL;
19085 xmlGenericError(xmlGenericErrorContext,
19086 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019087 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19088 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019089 FREE_AND_NULL(str)
19090 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019091#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019092 /*
19093 * Evaluate the state objects.
19094 */
19095 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019096 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19097 if (res == -1) {
19098 VERROR_INT("xmlSchemaXPathProcessHistory",
19099 "calling xmlStreamPop()");
19100 return (-1);
19101 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019102#if DEBUG_IDC
19103 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19104 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019105#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019106 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019107 goto deregister_check;
19108
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019109 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019110
19111 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019112 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019113 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019114 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019115 sto = sto->next;
19116 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019117 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019118 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19119 if (! IS_SIMPLE_TYPE(type)) {
19120 /*
19121 * Not qualified if the field resolves to a node of non
19122 * simple type.
19123 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019124 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19125 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019126 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19127 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019128 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019129
19130 sto->nbHistory--;
19131 goto deregister_check;
19132 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019133 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019134 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019135 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019136 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019137 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019138 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019139 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19140 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019141 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019142 sto->nbHistory--;
19143 goto deregister_check;
19144 } else {
19145 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19146 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019147 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019148
19149 /*
19150 * The key will be anchored on the matcher's list of
19151 * key-sequences. The position in this list is determined
19152 * by the target node's depth relative to the matcher's
19153 * depth of creation (i.e. the depth of the scope element).
19154 */
19155 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019156 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019157
19158 /*
19159 * Create/grow the array of key-sequences.
19160 */
19161 if (matcher->keySeqs == NULL) {
19162 if (pos > 9)
19163 matcher->sizeKeySeqs = pos * 2;
19164 else
19165 matcher->sizeKeySeqs = 10;
19166 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19167 xmlMalloc(matcher->sizeKeySeqs *
19168 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19169 if (matcher->keySeqs == NULL) {
19170 xmlSchemaVErrMemory(NULL,
19171 "allocating an array of key-sequences",
19172 NULL);
19173 return(-1);
19174 }
19175 memset(matcher->keySeqs, 0,
19176 matcher->sizeKeySeqs *
19177 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19178 } else if (pos >= matcher->sizeKeySeqs) {
19179 int i = matcher->sizeKeySeqs;
19180
19181 matcher->sizeKeySeqs *= 2;
19182 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19183 xmlRealloc(matcher->keySeqs,
19184 matcher->sizeKeySeqs *
19185 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019186 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019187 xmlSchemaVErrMemory(NULL,
19188 "reallocating an array of key-sequences",
19189 NULL);
19190 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019191 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019192 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019193 * The array needs to be NULLed.
19194 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019195 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019196 for (; i < matcher->sizeKeySeqs; i++)
19197 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019198 }
19199
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019200 /*
19201 * Get/create the key-sequence.
19202 */
19203 keySeq = matcher->keySeqs[pos];
19204 if (keySeq == NULL) {
19205 goto create_sequence;
19206 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019207 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019208 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019209 * cvc-identity-constraint:
19210 * 3 For each node in the ·target node set· all
19211 * of the {fields}, with that node as the context
19212 * node, evaluate to either an empty node-set or
19213 * a node-set with exactly one member, which must
19214 * have a simple type.
19215 *
19216 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019217 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019218 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19219 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019220 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019221 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019222 "with more than one member",
19223 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019224 sto->nbHistory--;
19225 goto deregister_check;
19226 } else {
19227 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019228 }
19229 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019230
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019231create_sequence:
19232 /*
19233 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019234 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019235 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19236 matcher->aidc->def->nbFields *
19237 sizeof(xmlSchemaPSVIIDCKeyPtr));
19238 if (keySeq == NULL) {
19239 xmlSchemaVErrMemory(NULL,
19240 "allocating an IDC key-sequence", NULL);
19241 return(-1);
19242 }
19243 memset(keySeq, 0, matcher->aidc->def->nbFields *
19244 sizeof(xmlSchemaPSVIIDCKeyPtr));
19245 matcher->keySeqs[pos] = keySeq;
19246create_key:
19247 /*
19248 * Created a key once per node only.
19249 */
19250 if (key == NULL) {
19251 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19252 sizeof(xmlSchemaPSVIIDCKey));
19253 if (key == NULL) {
19254 xmlSchemaVErrMemory(NULL,
19255 "allocating a IDC key", NULL);
19256 xmlFree(keySeq);
19257 matcher->keySeqs[pos] = NULL;
19258 return(-1);
19259 }
19260 /*
19261 * Consume the compiled value.
19262 */
19263 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019264 key->val = vctxt->inode->val;
19265 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019266 /*
19267 * Store the key in a global list.
19268 */
19269 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19270 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019271 return (-1);
19272 }
19273 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019274 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019275 }
19276 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019277
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019278 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19279 xmlSchemaPSVIIDCBindingPtr bind;
19280 xmlSchemaPSVIIDCNodePtr ntItem;
19281 xmlSchemaIDCMatcherPtr matcher;
19282 xmlSchemaIDCPtr idc;
19283 int pos, i, j, nbKeys;
19284 /*
19285 * Here we have the following scenario:
19286 * An IDC 'selector' state object resolved to a target node,
19287 * during the time this target node was in the
19288 * ancestor-or-self axis, the 'field' state object(s) looked
19289 * out for matching nodes to create a key-sequence for this
19290 * target node. Now we are back to this target node and need
19291 * to put the key-sequence, together with the target node
19292 * itself, into the node-table of the corresponding IDC
19293 * binding.
19294 */
19295 matcher = sto->matcher;
19296 idc = matcher->aidc->def;
19297 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019298 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019299 /*
19300 * Check if the matcher has any key-sequences at all, plus
19301 * if it has a key-sequence for the current target node.
19302 */
19303 if ((matcher->keySeqs == NULL) ||
19304 (matcher->sizeKeySeqs <= pos)) {
19305 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19306 goto selector_key_error;
19307 else
19308 goto selector_leave;
19309 }
19310
19311 keySeq = &(matcher->keySeqs[pos]);
19312 if (*keySeq == NULL) {
19313 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19314 goto selector_key_error;
19315 else
19316 goto selector_leave;
19317 }
19318
19319 for (i = 0; i < nbKeys; i++) {
19320 if ((*keySeq)[i] == NULL) {
19321 /*
19322 * Not qualified, if not all fields did resolve.
19323 */
19324 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19325 /*
19326 * All fields of a "key" IDC must resolve.
19327 */
19328 goto selector_key_error;
19329 }
19330 goto selector_leave;
19331 }
19332 }
19333 /*
19334 * All fields did resolve.
19335 */
19336
19337 /*
19338 * 4.1 If the {identity-constraint category} is unique(/key),
19339 * then no two members of the ·qualified node set· have
19340 * ·key-sequences· whose members are pairwise equal, as
19341 * defined by Equal in [XML Schemas: Datatypes].
19342 *
19343 * Get the IDC binding from the matcher and check for
19344 * duplicate key-sequences.
19345 */
19346 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19347 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19348 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019349 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019350
19351 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019352 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019353 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019354 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019355 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019356 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019357 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019358 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019359 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019360 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019361 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019362 if (res == -1) {
19363 return (-1);
19364 } else if (res == 0)
19365 break;
19366 }
19367 if (res == 1) {
19368 /*
19369 * Duplicate found.
19370 */
19371 break;
19372 }
19373 i++;
19374 } while (i < bind->nbNodes);
19375 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019376 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019377 /*
19378 * TODO: Try to report the key-sequence.
19379 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019380 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19381 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019382 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019383 "Duplicate key-sequence %s",
19384 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19385 (*keySeq), nbKeys), NULL);
19386 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019387 goto selector_leave;
19388 }
19389 }
19390 /*
19391 * Add a node-table item to the IDC binding.
19392 */
19393 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19394 sizeof(xmlSchemaPSVIIDCNode));
19395 if (ntItem == NULL) {
19396 xmlSchemaVErrMemory(NULL,
19397 "allocating an IDC node-table item", NULL);
19398 xmlFree(*keySeq);
19399 *keySeq = NULL;
19400 return(-1);
19401 }
19402 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19403
19404 /*
19405 * Store the node-table item on global list.
19406 */
19407 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19408 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19409 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019410 xmlFree(*keySeq);
19411 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019412 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019413 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019414 }
19415 /*
19416 * Init the node-table item. Consume the key-sequence.
19417 */
19418 ntItem->node = vctxt->node;
19419 ntItem->keys = *keySeq;
19420 *keySeq = NULL;
19421 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19422 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19423 /*
19424 * Free the item, since keyref items won't be
19425 * put on a global list.
19426 */
19427 xmlFree(ntItem->keys);
19428 xmlFree(ntItem);
19429 }
19430 return (-1);
19431 }
19432
19433 goto selector_leave;
19434selector_key_error:
19435 /*
19436 * 4.2.1 (KEY) The ·target node set· and the
19437 * ·qualified node set· are equal, that is, every
19438 * member of the ·target node set· is also a member
19439 * of the ·qualified node set· and vice versa.
19440 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019441 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19442 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019443selector_leave:
19444 /*
19445 * Free the key-sequence if not added to the IDC table.
19446 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019447 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019448 xmlFree(*keySeq);
19449 *keySeq = NULL;
19450 }
19451 } /* if selector */
19452
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019453 sto->nbHistory--;
19454
19455deregister_check:
19456 /*
19457 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019458 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019459 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019460#if DEBUG_IDC
19461 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19462 sto->sel->xpath);
19463#endif
19464 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019465 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019466 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019467 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019468 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019469 nextsto = sto->next;
19470 /*
19471 * Unlink from the list of active XPath state objects.
19472 */
19473 vctxt->xpathStates = sto->next;
19474 sto->next = vctxt->xpathStatePool;
19475 /*
19476 * Link it to the pool of reusable state objects.
19477 */
19478 vctxt->xpathStatePool = sto;
19479 sto = nextsto;
19480 } else
19481 sto = sto->next;
19482 } /* while (sto != NULL) */
19483 return (0);
19484}
19485
19486/**
19487 * xmlSchemaIDCRegisterMatchers:
19488 * @vctxt: the WXS validation context
19489 * @elemDecl: the element declaration
19490 *
19491 * Creates helper objects to evaluate IDC selectors/fields
19492 * successively.
19493 *
19494 * Returns 0 if OK and -1 on internal errors.
19495 */
19496static int
19497xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19498 xmlSchemaElementPtr elemDecl)
19499{
19500 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19501 xmlSchemaIDCPtr idc, refIdc;
19502 xmlSchemaIDCAugPtr aidc;
19503
19504 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19505 if (idc == NULL)
19506 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019507
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019508#if DEBUG_IDC
19509 {
19510 xmlChar *str = NULL;
19511 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019512 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019513 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19514 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019515 FREE_AND_NULL(str)
19516 }
19517#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019518 if (vctxt->inode->idcMatchers != NULL) {
19519 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19520 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019521 return (-1);
19522 }
19523 do {
19524 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19525 /*
19526 * Since IDCs bubbles are expensive we need to know the
19527 * depth at which the bubbles should stop; this will be
19528 * the depth of the top-most keyref IDC. If no keyref
19529 * references a key/unique IDC, the bubbleDepth will
19530 * be -1, indicating that no bubbles are needed.
19531 */
19532 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19533 if (refIdc != NULL) {
19534 /*
19535 * Lookup the augmented IDC.
19536 */
19537 aidc = vctxt->aidcs;
19538 while (aidc != NULL) {
19539 if (aidc->def == refIdc)
19540 break;
19541 aidc = aidc->next;
19542 }
19543 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019544 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019545 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019546 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019547 return (-1);
19548 }
19549 if ((aidc->bubbleDepth == -1) ||
19550 (vctxt->depth < aidc->bubbleDepth))
19551 aidc->bubbleDepth = vctxt->depth;
19552 }
19553 }
19554 /*
19555 * Lookup the augmented IDC item for the IDC definition.
19556 */
19557 aidc = vctxt->aidcs;
19558 while (aidc != NULL) {
19559 if (aidc->def == idc)
19560 break;
19561 aidc = aidc->next;
19562 }
19563 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019564 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19565 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019566 return (-1);
19567 }
19568 /*
19569 * Create an IDC matcher for every IDC definition.
19570 */
19571 matcher = (xmlSchemaIDCMatcherPtr)
19572 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19573 if (matcher == NULL) {
19574 xmlSchemaVErrMemory(vctxt,
19575 "allocating an IDC matcher", NULL);
19576 return (-1);
19577 }
19578 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19579 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019580 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019581 else
19582 last->next = matcher;
19583 last = matcher;
19584
19585 matcher->type = IDC_MATCHER;
19586 matcher->depth = vctxt->depth;
19587 matcher->aidc = aidc;
19588#if DEBUG_IDC
19589 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19590#endif
19591 /*
19592 * Init the automaton state object.
19593 */
19594 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019595 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019596 return (-1);
19597
19598 idc = idc->next;
19599 } while (idc != NULL);
19600 return (0);
19601}
19602
19603/**
19604 * xmlSchemaBubbleIDCNodeTables:
19605 * @depth: the current tree depth
19606 *
19607 * Merges IDC bindings of an element at @depth into the corresponding IDC
19608 * bindings of its parent element. If a duplicate note-table entry is found,
19609 * both, the parent node-table entry and child entry are discarded from the
19610 * node-table of the parent.
19611 *
19612 * Returns 0 if OK and -1 on internal errors.
19613 */
19614static int
19615xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19616{
19617 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019618 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19619 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019620 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19621 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019622 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019623 int duplTop;
19624
19625 /*
19626 * The node table has the following sections:
19627 *
19628 * O --> old node-table entries (first)
19629 * O
19630 * + --> new node-table entries
19631 * +
19632 * % --> new duplicate node-table entries
19633 * %
19634 * # --> old duplicate node-table entries
19635 * # (last)
19636 *
19637 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019638 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019639 if (bind == NULL) {
19640 /* Fine, no table, no bubbles. */
19641 return (0);
19642 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019643
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019644 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19645 /*
19646 * Walk all bindings; create new or add to existing bindings.
19647 * Remove duplicate key-sequences.
19648 */
19649start_binding:
19650 while (bind != NULL) {
19651 /*
19652 * Skip keyref IDCs.
19653 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019654 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19655 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019656 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019657 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019658 /*
19659 * Check if the key/unique IDC table needs to be bubbled.
19660 */
19661 aidc = vctxt->aidcs;
19662 do {
19663 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019664 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019665 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019666 bind = bind->next;
19667 goto start_binding;
19668 }
19669 break;
19670 }
19671 aidc = aidc->next;
19672 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019673
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019674 if (parTable != NULL)
19675 parBind = *parTable;
19676 while (parBind != NULL) {
19677 /*
19678 * Search a matching parent binding for the
19679 * IDC definition.
19680 */
19681 if (parBind->definition == bind->definition) {
19682
19683 /*
19684 * Compare every node-table entry of the child node,
19685 * i.e. the key-sequence within, ...
19686 */
19687 oldNum = parBind->nbNodes; /* Skip newly added items. */
19688 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019689 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019690
19691 for (i = 0; i < bind->nbNodes; i++) {
19692 node = bind->nodeTable[i];
19693 if (node == NULL)
19694 continue;
19695 /*
19696 * ...with every key-sequence of the parent node, already
19697 * evaluated to be a duplicate key-sequence.
19698 */
19699 if (parBind->nbDupls != 0) {
19700 j = bind->nbNodes + newDupls;
19701 while (j < duplTop) {
19702 parNode = parBind->nodeTable[j];
19703 for (k = 0; k < bind->definition->nbFields; k++) {
19704 key = node->keys[k];
19705 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019706 ret = xmlSchemaAreValuesEqual(key->val,
19707 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019708 if (ret == -1) {
19709 /* TODO: Internal error */
19710 return(-1);
19711 } else if (ret == 0)
19712 break;
19713
19714 }
19715 if (ret == 1)
19716 /* Duplicate found. */
19717 break;
19718 j++;
19719 }
19720 if (j != duplTop) {
19721 /* Duplicate found. */
19722 continue;
19723 }
19724 }
19725 /*
19726 * ... and with every key-sequence of the parent node.
19727 */
19728 j = 0;
19729 while (j < oldNum) {
19730 parNode = parBind->nodeTable[j];
19731 /*
19732 * Compare key by key.
19733 */
19734 for (k = 0; k < parBind->definition->nbFields; k++) {
19735 key = node->keys[k];
19736 parKey = parNode->keys[k];
19737
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019738 ret = xmlSchemaAreValuesEqual(key->val,
19739 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019740 if (ret == -1) {
19741 /* TODO: Internal error */
19742 } else if (ret == 0)
19743 break;
19744
19745 }
19746 if (ret == 1)
19747 /*
19748 * The key-sequences are equal.
19749 */
19750 break;
19751 j++;
19752 }
19753 if (j != oldNum) {
19754 /*
19755 * Handle duplicates.
19756 */
19757 newDupls++;
19758 oldNum--;
19759 parBind->nbNodes--;
19760 /*
19761 * Move last old item to pos of duplicate.
19762 */
19763 parBind->nodeTable[j] =
19764 parBind->nodeTable[oldNum];
19765
19766 if (parBind->nbNodes != oldNum) {
19767 /*
19768 * If new items exist, move last new item to
19769 * last of old items.
19770 */
19771 parBind->nodeTable[oldNum] =
19772 parBind->nodeTable[parBind->nbNodes];
19773 }
19774 /*
19775 * Move duplicate to last pos of new/old items.
19776 */
19777 parBind->nodeTable[parBind->nbNodes] = parNode;
19778
19779 } else {
19780 /*
19781 * Add the node-table entry (node and key-sequence) of
19782 * the child node to the node table of the parent node.
19783 */
19784 if (parBind->nodeTable == NULL) {
19785 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019786 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019787 if (parBind->nodeTable == NULL) {
19788 xmlSchemaVErrMemory(NULL,
19789 "allocating IDC list of node-table items", NULL);
19790 return(-1);
19791 }
19792 parBind->sizeNodes = 1;
19793 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019794 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019795 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19796 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19797 sizeof(xmlSchemaPSVIIDCNodePtr));
19798 if (parBind->nodeTable == NULL) {
19799 xmlSchemaVErrMemory(NULL,
19800 "re-allocating IDC list of node-table items", NULL);
19801 return(-1);
19802 }
19803 }
19804
19805 /*
19806 * Move first old duplicate to last position
19807 * of old duplicates +1.
19808 */
19809 if (parBind->nbDupls != 0) {
19810 parBind->nodeTable[duplTop] =
19811 parBind->nodeTable[parBind->nbNodes + newDupls];
19812 }
19813 /*
19814 * Move first new duplicate to last position of
19815 * new duplicates +1.
19816 */
19817 if (newDupls != 0) {
19818 parBind->nodeTable[parBind->nbNodes + newDupls] =
19819 parBind->nodeTable[parBind->nbNodes];
19820 }
19821 /*
19822 * Append the new node-table entry to the 'new node-table
19823 * entries' section.
19824 */
19825 parBind->nodeTable[parBind->nbNodes] = node;
19826 parBind->nbNodes++;
19827 duplTop++;
19828 }
19829 }
19830 parBind->nbDupls += newDupls;
19831 break;
19832 }
19833 if (parBind->next == NULL)
19834 lastParBind = parBind;
19835 parBind = parBind->next;
19836 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019837 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019838 /*
19839 * No binding for the IDC was found: create a new one and
19840 * copy all node-tables.
19841 */
19842 parBind = xmlSchemaIDCNewBinding(bind->definition);
19843 if (parBind == NULL)
19844 return(-1);
19845
19846 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19847 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19848 if (parBind->nodeTable == NULL) {
19849 xmlSchemaVErrMemory(NULL,
19850 "allocating an array of IDC node-table items", NULL);
19851 xmlSchemaIDCFreeBinding(parBind);
19852 return(-1);
19853 }
19854 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019855 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019856 memcpy(parBind->nodeTable, bind->nodeTable,
19857 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019858 if (*parTable == NULL)
19859 *parTable = parBind;
19860 else
19861 lastParBind->next = parBind;
19862 }
19863 bind = bind->next;
19864 }
19865 return (0);
19866}
19867
19868/**
19869 * xmlSchemaCheckCVCIDCKeyRef:
19870 * @vctxt: the WXS validation context
19871 * @elemDecl: the element declaration
19872 *
19873 * Check the cvc-idc-keyref constraints.
19874 */
19875static int
19876xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19877{
19878 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19879
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019880 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019881 /*
19882 * Find a keyref.
19883 */
19884 while (refbind != NULL) {
19885 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19886 int i, j, k, res;
19887 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19888 xmlSchemaPSVIIDCKeyPtr refKey, key;
19889
19890 /*
19891 * Find the referred key/unique.
19892 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019893 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019894 do {
19895 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19896 bind->definition)
19897 break;
19898 bind = bind->next;
19899 } while (bind != NULL);
19900
19901 /*
19902 * Search for a matching key-sequences.
19903 */
19904 for (i = 0; i < refbind->nbNodes; i++) {
19905 res = 0;
19906 if (bind != NULL) {
19907 refKeys = refbind->nodeTable[i]->keys;
19908 for (j = 0; j < bind->nbNodes; j++) {
19909 keys = bind->nodeTable[j]->keys;
19910 for (k = 0; k < bind->definition->nbFields; k++) {
19911 refKey = refKeys[k];
19912 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019913 res = xmlSchemaAreValuesEqual(key->val,
19914 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019915 if (res == 0)
19916 break;
19917 else if (res == -1) {
19918 return (-1);
19919 }
19920 }
19921 if (res == 1) {
19922 /*
19923 * Match found.
19924 */
19925 break;
19926 }
19927 }
19928 }
19929 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019930 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019931 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019932 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19933 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019934 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019935 "No match found for key-sequence %s of key "
19936 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019937 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019938 refbind->nodeTable[i]->keys,
19939 refbind->definition->nbFields),
19940 xmlSchemaFormatQName(&strB,
19941 refbind->definition->targetNamespace,
19942 refbind->definition->name));
19943 FREE_AND_NULL(str);
19944 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019945 }
19946 }
19947 }
19948 refbind = refbind->next;
19949 }
19950 return (0);
19951}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019952
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019953/************************************************************************
19954 * *
19955 * XML Reader validation code *
19956 * *
19957 ************************************************************************/
19958
19959static xmlSchemaAttrInfoPtr
19960xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019961{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019962 xmlSchemaAttrInfoPtr iattr;
19963 /*
19964 * Grow/create list of attribute infos.
19965 */
19966 if (vctxt->attrInfos == NULL) {
19967 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19968 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
19969 vctxt->sizeAttrInfos = 1;
19970 if (vctxt->attrInfos == NULL) {
19971 xmlSchemaVErrMemory(vctxt,
19972 "allocating attribute info list", NULL);
19973 return (NULL);
19974 }
19975 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
19976 vctxt->sizeAttrInfos++;
19977 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19978 xmlRealloc(vctxt->attrInfos,
19979 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
19980 if (vctxt->attrInfos == NULL) {
19981 xmlSchemaVErrMemory(vctxt,
19982 "re-allocating attribute info list", NULL);
19983 return (NULL);
19984 }
19985 } else {
19986 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
19987 if (iattr->localName != NULL) {
19988 VERROR_INT("xmlSchemaGetFreshAttrInfo",
19989 "attr info not cleared");
19990 return (NULL);
19991 }
19992 iattr->nodeType = XML_ATTRIBUTE_NODE;
19993 return (iattr);
19994 }
19995 /*
19996 * Create an attribute info.
19997 */
19998 iattr = (xmlSchemaAttrInfoPtr)
19999 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20000 if (iattr == NULL) {
20001 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20002 return (NULL);
20003 }
20004 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20005 iattr->nodeType = XML_ATTRIBUTE_NODE;
20006 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20007
20008 return (iattr);
20009}
20010
20011static int
20012xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20013 xmlNodePtr attrNode,
20014 const xmlChar *localName,
20015 const xmlChar *nsName,
20016 int ownedNames,
20017 xmlChar *value,
20018 int ownedValue)
20019{
20020 xmlSchemaAttrInfoPtr attr;
20021
20022 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20023 if (attr == NULL) {
20024 VERROR_INT("xmlSchemaPushAttribute",
20025 "calling xmlSchemaGetFreshAttrInfo()");
20026 return (-1);
20027 }
20028 attr->node = attrNode;
20029 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20030 attr->localName = localName;
20031 attr->nsName = nsName;
20032 if (ownedNames)
20033 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20034 /*
20035 * Evaluate if it's an XSI attribute.
20036 */
20037 if (nsName != NULL) {
20038 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20039 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20040 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20041 }
20042 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20043 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20044 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20045 }
20046 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20047 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20048 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20049 }
20050 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20051 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20052 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20053 }
20054 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20055 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20056 }
20057 }
20058 attr->value = value;
20059 if (ownedValue)
20060 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20061 if (attr->metaType != 0)
20062 attr->state = XML_SCHEMAS_ATTR_META;
20063 return (0);
20064}
20065
20066static void
20067xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20068{
20069 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20070 FREE_AND_NULL(ielem->localName);
20071 FREE_AND_NULL(ielem->nsName);
20072 } else {
20073 ielem->localName = NULL;
20074 ielem->nsName = NULL;
20075 }
20076 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20077 FREE_AND_NULL(ielem->value);
20078 } else {
20079 ielem->value = NULL;
20080 }
20081 if (ielem->val != NULL) {
20082 xmlSchemaFreeValue(ielem->val);
20083 ielem->val = NULL;
20084 }
20085 if (ielem->idcMatchers != NULL) {
20086 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20087 ielem->idcMatchers = NULL;
20088 }
20089 if (ielem->idcTable != NULL) {
20090 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20091 ielem->idcTable = NULL;
20092 }
20093 if (ielem->regexCtxt != NULL) {
20094 xmlRegFreeExecCtxt(ielem->regexCtxt);
20095 ielem->regexCtxt = NULL;
20096 }
20097 if (ielem->nsBindings != NULL) {
20098 xmlFree((xmlChar **)ielem->nsBindings);
20099 ielem->nsBindings = NULL;
20100 ielem->nbNsBindings = 0;
20101 ielem->sizeNsBindings = 0;
20102 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020103}
20104
20105/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020106 * xmlSchemaGetFreshElemInfo:
20107 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020108 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020109 * Creates/reuses and initializes the element info item for
20110 * the currect tree depth.
20111 *
20112 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020113 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020114static xmlSchemaNodeInfoPtr
20115xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020116{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020117 xmlSchemaNodeInfoPtr info = NULL;
20118
20119 if (vctxt->depth > vctxt->sizeElemInfos) {
20120 VERROR_INT("xmlSchemaGetFreshElemInfo",
20121 "inconsistent depth encountered");
20122 return (NULL);
20123 }
20124 if (vctxt->elemInfos == NULL) {
20125 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20126 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20127 if (vctxt->elemInfos == NULL) {
20128 xmlSchemaVErrMemory(vctxt,
20129 "allocating the element info array", NULL);
20130 return (NULL);
20131 }
20132 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20133 vctxt->sizeElemInfos = 10;
20134 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20135 int i = vctxt->sizeElemInfos;
20136
20137 vctxt->sizeElemInfos *= 2;
20138 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20139 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20140 sizeof(xmlSchemaNodeInfoPtr));
20141 if (vctxt->elemInfos == NULL) {
20142 xmlSchemaVErrMemory(vctxt,
20143 "re-allocating the element info array", NULL);
20144 return (NULL);
20145 }
20146 /*
20147 * We need the new memory to be NULLed.
20148 * TODO: Use memset instead?
20149 */
20150 for (; i < vctxt->sizeElemInfos; i++)
20151 vctxt->elemInfos[i] = NULL;
20152 } else
20153 info = vctxt->elemInfos[vctxt->depth];
20154
20155 if (info == NULL) {
20156 info = (xmlSchemaNodeInfoPtr)
20157 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20158 if (info == NULL) {
20159 xmlSchemaVErrMemory(vctxt,
20160 "allocating an element info", NULL);
20161 return (NULL);
20162 }
20163 vctxt->elemInfos[vctxt->depth] = info;
20164 } else {
20165 if (info->localName != NULL) {
20166 VERROR_INT("xmlSchemaGetFreshElemInfo",
20167 "elem info has not been cleared");
20168 return (NULL);
20169 }
20170 }
20171 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20172 info->nodeType = XML_ELEMENT_NODE;
20173 info->depth = vctxt->depth;
20174
20175 return (info);
20176}
20177
20178#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20179#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20180#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20181
20182static int
20183xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20184 xmlNodePtr node,
20185 xmlSchemaTypePtr type,
20186 xmlSchemaValType valType,
20187 const xmlChar * value,
20188 xmlSchemaValPtr val,
20189 unsigned long length,
20190 int fireErrors)
20191{
20192 int ret, error = 0;
20193
20194 xmlSchemaTypePtr tmpType;
20195 xmlSchemaFacetLinkPtr facetLink;
20196 xmlSchemaFacetPtr facet;
20197 unsigned long len = 0;
20198 xmlSchemaWhitespaceValueType ws;
20199
20200 /*
20201 * In Libxml2, derived built-in types have currently no explicit facets.
20202 */
20203 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020204 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020205
20206 /*
20207 * NOTE: Do not jump away, if the facetSet of the given type is
20208 * empty: until now, "pattern" and "enumeration" facets of the
20209 * *base types* need to be checked as well.
20210 */
20211 if (type->facetSet == NULL)
20212 goto pattern_and_enum;
20213
20214 if (! VARIETY_ATOMIC(type)) {
20215 if (VARIETY_LIST(type))
20216 goto variety_list;
20217 else
20218 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020219 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020220 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020221 * Whitespace handling is only of importance for string-based
20222 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020223 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020224 tmpType = xmlSchemaGetPrimitiveType(type);
20225 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20226 IS_ANY_SIMPLE_TYPE(tmpType)) {
20227 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20228 } else
20229 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20230 /*
20231 * If the value was not computed (for string or
20232 * anySimpleType based types), then use the provided
20233 * type.
20234 */
20235 if (val == NULL)
20236 valType = valType;
20237 else
20238 valType = xmlSchemaGetValType(val);
20239
20240 ret = 0;
20241 for (facetLink = type->facetSet; facetLink != NULL;
20242 facetLink = facetLink->next) {
20243 /*
20244 * Skip the pattern "whiteSpace": it is used to
20245 * format the character content beforehand.
20246 */
20247 switch (facetLink->facet->type) {
20248 case XML_SCHEMA_FACET_WHITESPACE:
20249 case XML_SCHEMA_FACET_PATTERN:
20250 case XML_SCHEMA_FACET_ENUMERATION:
20251 continue;
20252 case XML_SCHEMA_FACET_LENGTH:
20253 case XML_SCHEMA_FACET_MINLENGTH:
20254 case XML_SCHEMA_FACET_MAXLENGTH:
20255 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20256 valType, value, val, &len, ws);
20257 break;
20258 default:
20259 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20260 valType, value, val, ws);
20261 break;
20262 }
20263 if (ret < 0) {
20264 AERROR_INT("xmlSchemaValidateFacets",
20265 "validating against a atomic type facet");
20266 return (-1);
20267 } else if (ret > 0) {
20268 if (fireErrors)
20269 xmlSchemaFacetErr(actxt, ret, node,
20270 value, len, type, facetLink->facet, NULL, NULL, NULL);
20271 else
20272 return (ret);
20273 if (error == 0)
20274 error = ret;
20275 }
20276 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020277 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020278
20279variety_list:
20280 if (! VARIETY_LIST(type))
20281 goto pattern_and_enum;
20282 /*
20283 * "length", "minLength" and "maxLength" of list types.
20284 */
20285 ret = 0;
20286 for (facetLink = type->facetSet; facetLink != NULL;
20287 facetLink = facetLink->next) {
20288
20289 switch (facetLink->facet->type) {
20290 case XML_SCHEMA_FACET_LENGTH:
20291 case XML_SCHEMA_FACET_MINLENGTH:
20292 case XML_SCHEMA_FACET_MAXLENGTH:
20293 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20294 value, length, NULL);
20295 break;
20296 default:
20297 continue;
20298 }
20299 if (ret < 0) {
20300 AERROR_INT("xmlSchemaValidateFacets",
20301 "validating against a list type facet");
20302 return (-1);
20303 } else if (ret > 0) {
20304 if (fireErrors)
20305 xmlSchemaFacetErr(actxt, ret, node,
20306 value, length, type, facetLink->facet, NULL, NULL, NULL);
20307 else
20308 return (ret);
20309 if (error == 0)
20310 error = ret;
20311 }
20312 ret = 0;
20313 }
20314
20315pattern_and_enum:
20316 if (error >= 0) {
20317 int found = 0;
20318 /*
20319 * Process enumerations. Facet values are in the value space
20320 * of the defining type's base type. This seems to be a bug in the
20321 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20322 * Only the first set of enumerations in the ancestor-or-self axis
20323 * is used for validation.
20324 */
20325 ret = 0;
20326 tmpType = type;
20327 do {
20328 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20329 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20330 continue;
20331 found = 1;
20332 ret = xmlSchemaAreValuesEqual(facet->val, val);
20333 if (ret == 1)
20334 break;
20335 else if (ret < 0) {
20336 AERROR_INT("xmlSchemaValidateFacets",
20337 "validating against an enumeration facet");
20338 return (-1);
20339 }
20340 }
20341 if (ret != 0)
20342 break;
20343 tmpType = tmpType->baseType;
20344 } while ((tmpType != NULL) &&
20345 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20346 if (found && (ret == 0)) {
20347 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20348 if (fireErrors) {
20349 xmlSchemaFacetErr(actxt, ret, node,
20350 value, 0, type, NULL, NULL, NULL, NULL);
20351 } else
20352 return (ret);
20353 if (error == 0)
20354 error = ret;
20355 }
20356 }
20357
20358 if (error >= 0) {
20359 int found;
20360 /*
20361 * Process patters. Pattern facets are ORed at type level
20362 * and ANDed if derived. Walk the base type axis.
20363 */
20364 tmpType = type;
20365 facet = NULL;
20366 do {
20367 found = 0;
20368 for (facetLink = tmpType->facetSet; facetLink != NULL;
20369 facetLink = facetLink->next) {
20370 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20371 continue;
20372 found = 1;
20373 /*
20374 * NOTE that for patterns, @value needs to be the
20375 * normalized vaule.
20376 */
20377 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20378 if (ret == 1)
20379 break;
20380 else if (ret < 0) {
20381 AERROR_INT("xmlSchemaValidateFacets",
20382 "validating against a pattern facet");
20383 return (-1);
20384 } else {
20385 /*
20386 * Save the last non-validating facet.
20387 */
20388 facet = facetLink->facet;
20389 }
20390 }
20391 if (found && (ret != 1)) {
20392 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20393 if (fireErrors) {
20394 xmlSchemaFacetErr(actxt, ret, node,
20395 value, 0, type, facet, NULL, NULL, NULL);
20396 } else
20397 return (ret);
20398 if (error == 0)
20399 error = ret;
20400 break;
20401 }
20402 tmpType = tmpType->baseType;
20403 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20404 }
20405
20406 return (error);
20407}
20408
20409static xmlChar *
20410xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20411 const xmlChar *value)
20412{
20413 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20414 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20415 return (xmlSchemaCollapseString(value));
20416 case XML_SCHEMA_WHITESPACE_REPLACE:
20417 return (xmlSchemaWhiteSpaceReplace(value));
20418 default:
20419 return (NULL);
20420 }
20421}
20422
20423static int
20424xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20425 const xmlChar *value,
20426 xmlSchemaValPtr *val,
20427 int valNeeded)
20428{
20429 int ret;
20430 const xmlChar *nsName;
20431 xmlChar *local, *prefix = NULL;
20432
20433 ret = xmlValidateQName(value, 1);
20434 if (ret != 0) {
20435 if (ret == -1) {
20436 VERROR_INT("xmlSchemaValidateQName",
20437 "calling xmlValidateQName()");
20438 return (-1);
20439 }
20440 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20441 }
20442 /*
20443 * NOTE: xmlSplitQName2 will always return a duplicated
20444 * strings.
20445 */
20446 local = xmlSplitQName2(value, &prefix);
20447 if (local == NULL)
20448 local = xmlStrdup(value);
20449 /*
20450 * OPTIMIZE TODO: Use flags for:
20451 * - is there any namespace binding?
20452 * - is there a default namespace?
20453 */
20454 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20455
20456 if (prefix != NULL) {
20457 xmlFree(prefix);
20458 /*
20459 * A namespace must be found if the prefix is
20460 * NOT NULL.
20461 */
20462 if (nsName == NULL) {
20463 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20464 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20465 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20466 "The QName value '%s' has no "
20467 "corresponding namespace declaration in "
20468 "scope", value, NULL);
20469 if (local != NULL)
20470 xmlFree(local);
20471 return (ret);
20472 }
20473 }
20474 if (valNeeded && val) {
20475 if (nsName != NULL)
20476 *val = xmlSchemaNewQNameValue(
20477 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20478 else
20479 *val = xmlSchemaNewQNameValue(NULL,
20480 BAD_CAST local);
20481 } else
20482 xmlFree(local);
20483 return (0);
20484}
20485
20486/*
20487* cvc-simple-type
20488*/
20489static int
20490xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20491 xmlNodePtr node,
20492 xmlSchemaTypePtr type,
20493 const xmlChar *value,
20494 xmlSchemaValPtr *retVal,
20495 int fireErrors,
20496 int normalize,
20497 int isNormalized)
20498{
20499 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20500 xmlSchemaValPtr val = NULL;
20501 xmlSchemaWhitespaceValueType ws;
20502 xmlChar *normValue = NULL;
20503
20504#define NORMALIZE(atype) \
20505 if ((! isNormalized) && \
20506 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20507 normValue = xmlSchemaNormalizeValue(atype, value); \
20508 if (normValue != NULL) \
20509 value = normValue; \
20510 isNormalized = 1; \
20511 }
20512
20513 if ((retVal != NULL) && (*retVal != NULL)) {
20514 xmlSchemaFreeValue(*retVal);
20515 *retVal = NULL;
20516 }
20517 /*
20518 * 3.14.4 Simple Type Definition Validation Rules
20519 * Validation Rule: String Valid
20520 */
20521 /*
20522 * 1 It is schema-valid with respect to that definition as defined
20523 * by Datatype Valid in [XML Schemas: Datatypes].
20524 */
20525 /*
20526 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20527 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20528 * the string must be a ·declared entity name·.
20529 */
20530 /*
20531 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20532 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20533 * then every whitespace-delimited substring of the string must be a ·declared
20534 * entity name·.
20535 */
20536 /*
20537 * 2.3 otherwise no further condition applies.
20538 */
20539 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20540 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020541 if (value == NULL)
20542 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020543 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20544 xmlSchemaTypePtr biType; /* The built-in type. */
20545 /*
20546 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20547 * a literal in the ·lexical space· of {base type definition}"
20548 */
20549 /*
20550 * Whitespace-normalize.
20551 */
20552 NORMALIZE(type);
20553 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20554 /*
20555 * Get the built-in type.
20556 */
20557 biType = type->baseType;
20558 while ((biType != NULL) &&
20559 (biType->type != XML_SCHEMA_TYPE_BASIC))
20560 biType = biType->baseType;
20561
20562 if (biType == NULL) {
20563 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20564 "could not get the built-in type");
20565 goto internal_error;
20566 }
20567 } else
20568 biType = type;
20569 /*
20570 * NOTATIONs need to be processed here, since they need
20571 * to lookup in the hashtable of NOTATION declarations of the schema.
20572 */
20573 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20574 switch (biType->builtInType) {
20575 case XML_SCHEMAS_NOTATION:
20576 ret = xmlSchemaValidateNotation(
20577 (xmlSchemaValidCtxtPtr) actxt,
20578 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20579 NULL, value, &val, valNeeded);
20580 break;
20581 case XML_SCHEMAS_QNAME:
20582 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20583 value, &val, valNeeded);
20584 break;
20585 default:
20586 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20587 if (valNeeded)
20588 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20589 value, &val, NULL);
20590 else
20591 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20592 value, NULL, NULL);
20593 break;
20594 }
20595 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20596 switch (biType->builtInType) {
20597 case XML_SCHEMAS_NOTATION:
20598 ret = xmlSchemaValidateNotation(NULL,
20599 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20600 value, &val, valNeeded);
20601 break;
20602 default:
20603 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20604 if (valNeeded)
20605 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20606 value, &val, node);
20607 else
20608 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20609 value, NULL, node);
20610 break;
20611 }
20612 } else {
20613 /*
20614 * Validation via a public API is not implemented yet.
20615 */
20616 TODO
20617 goto internal_error;
20618 }
20619 if (ret != 0) {
20620 if (ret < 0) {
20621 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20622 "validating against a built-in type");
20623 goto internal_error;
20624 }
20625 if (VARIETY_LIST(type))
20626 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20627 else
20628 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20629 }
20630 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20631 /*
20632 * Check facets.
20633 */
20634 ret = xmlSchemaValidateFacets(actxt, node, type,
20635 (xmlSchemaValType) biType->builtInType, value, val,
20636 0, fireErrors);
20637 if (ret != 0) {
20638 if (ret < 0) {
20639 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20640 "validating facets of atomic simple type");
20641 goto internal_error;
20642 }
20643 if (VARIETY_LIST(type))
20644 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20645 else
20646 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20647 }
20648 }
20649 if (fireErrors && (ret > 0))
20650 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20651 } else if (VARIETY_LIST(type)) {
20652
20653 xmlSchemaTypePtr itemType;
20654 const xmlChar *cur, *end;
20655 xmlChar *tmpValue = NULL;
20656 unsigned long len = 0;
20657 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20658 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20659 * of white space separated tokens, each of which ·match·es a literal
20660 * in the ·lexical space· of {item type definition}
20661 */
20662 /*
20663 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20664 * the list type has an enum or pattern facet.
20665 */
20666 NORMALIZE(type);
20667 /*
20668 * VAL TODO: Optimize validation of empty values.
20669 * VAL TODO: We do not have computed values for lists.
20670 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020671 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020672 cur = value;
20673 do {
20674 while (IS_BLANK_CH(*cur))
20675 cur++;
20676 end = cur;
20677 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20678 end++;
20679 if (end == cur)
20680 break;
20681 tmpValue = xmlStrndup(cur, end - cur);
20682 len++;
20683
20684 if (valNeeded)
20685 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20686 tmpValue, &curVal, fireErrors, 0, 1);
20687 else
20688 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20689 tmpValue, NULL, fireErrors, 0, 1);
20690 FREE_AND_NULL(tmpValue);
20691 if (curVal != NULL) {
20692 /*
20693 * Add to list of computed values.
20694 */
20695 if (val == NULL)
20696 val = curVal;
20697 else
20698 xmlSchemaValueAppend(prevVal, curVal);
20699 prevVal = curVal;
20700 curVal = NULL;
20701 }
20702 if (ret != 0) {
20703 if (ret < 0) {
20704 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20705 "validating an item of list simple type");
20706 goto internal_error;
20707 }
20708 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20709 break;
20710 }
20711 cur = end;
20712 } while (*cur != 0);
20713 FREE_AND_NULL(tmpValue);
20714 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20715 /*
20716 * Apply facets (pattern, enumeration).
20717 */
20718 ret = xmlSchemaValidateFacets(actxt, node, type,
20719 XML_SCHEMAS_UNKNOWN, value, val,
20720 len, fireErrors);
20721 if (ret != 0) {
20722 if (ret < 0) {
20723 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20724 "validating facets of list simple type");
20725 goto internal_error;
20726 }
20727 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20728 }
20729 }
20730 if (fireErrors && (ret > 0)) {
20731 /*
20732 * Report the normalized value.
20733 */
20734 normalize = 1;
20735 NORMALIZE(type);
20736 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20737 }
20738 } else if (VARIETY_UNION(type)) {
20739 xmlSchemaTypeLinkPtr memberLink;
20740 /*
20741 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20742 * not apply directly; however, the normalization behavior of ·union·
20743 * types is controlled by the value of whiteSpace on that one of the
20744 * ·memberTypes· against which the ·union· is successfully validated.
20745 *
20746 * This means that the value is normalized by the first validating
20747 * member type, then the facets of the union type are applied. This
20748 * needs changing of the value!
20749 */
20750
20751 /*
20752 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20753 * literal in the ·lexical space· of at least one member of
20754 * {member type definitions}
20755 */
20756 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20757 if (memberLink == NULL) {
20758 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20759 "union simple type has no member types");
20760 goto internal_error;
20761 }
20762 /*
20763 * Always normalize union type values, since we currently
20764 * cannot store the whitespace information with the value
20765 * itself; otherwise a later value-comparison would be
20766 * not possible.
20767 */
20768 while (memberLink != NULL) {
20769 if (valNeeded)
20770 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20771 memberLink->type, value, &val, 0, 1, 0);
20772 else
20773 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20774 memberLink->type, value, NULL, 0, 1, 0);
20775 if (ret <= 0)
20776 break;
20777 memberLink = memberLink->next;
20778 }
20779 if (ret != 0) {
20780 if (ret < 0) {
20781 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20782 "validating members of union simple type");
20783 goto internal_error;
20784 }
20785 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20786 }
20787 /*
20788 * Apply facets (pattern, enumeration).
20789 */
20790 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20791 /*
20792 * The normalization behavior of ·union· types is controlled by
20793 * the value of whiteSpace on that one of the ·memberTypes·
20794 * against which the ·union· is successfully validated.
20795 */
20796 NORMALIZE(memberLink->type);
20797 ret = xmlSchemaValidateFacets(actxt, node, type,
20798 XML_SCHEMAS_UNKNOWN, value, val,
20799 0, fireErrors);
20800 if (ret != 0) {
20801 if (ret < 0) {
20802 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20803 "validating facets of union simple type");
20804 goto internal_error;
20805 }
20806 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20807 }
20808 }
20809 if (fireErrors && (ret > 0))
20810 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20811 }
20812
20813 if (normValue != NULL)
20814 xmlFree(normValue);
20815 if (ret == 0) {
20816 if (retVal != NULL)
20817 *retVal = val;
20818 else if (val != NULL)
20819 xmlSchemaFreeValue(val);
20820 } else if (val != NULL)
20821 xmlSchemaFreeValue(val);
20822 return (ret);
20823internal_error:
20824 if (normValue != NULL)
20825 xmlFree(normValue);
20826 if (val != NULL)
20827 xmlSchemaFreeValue(val);
20828 return (-1);
20829}
20830
20831static int
20832xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20833 const xmlChar *value,
20834 const xmlChar **nsName,
20835 const xmlChar **localName)
20836{
20837 int ret = 0;
20838
20839 if ((nsName == NULL) || (localName == NULL))
20840 return (-1);
20841 *nsName = NULL;
20842 *localName = NULL;
20843
20844 ret = xmlValidateQName(value, 1);
20845 if (ret == -1)
20846 return (-1);
20847 if (ret > 0) {
20848 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20849 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20850 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20851 return (1);
20852 }
20853 {
20854 xmlChar *local = NULL;
20855 xmlChar *prefix;
20856
20857 /*
20858 * NOTE: xmlSplitQName2 will return a duplicated
20859 * string.
20860 */
20861 local = xmlSplitQName2(value, &prefix);
20862 VAL_CREATE_DICT;
20863 if (local == NULL)
20864 *localName = xmlDictLookup(vctxt->dict, value, -1);
20865 else {
20866 *localName = xmlDictLookup(vctxt->dict, local, -1);
20867 xmlFree(local);
20868 }
20869
20870 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20871
20872 if (prefix != NULL) {
20873 xmlFree(prefix);
20874 /*
20875 * A namespace must be found if the prefix is NOT NULL.
20876 */
20877 if (*nsName == NULL) {
20878 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20879 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20880 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20881 "The QName value '%s' has no "
20882 "corresponding namespace declaration in scope",
20883 value, NULL);
20884 return (2);
20885 }
20886 }
20887 }
20888 return (0);
20889}
20890
20891static int
20892xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20893 xmlSchemaAttrInfoPtr iattr,
20894 xmlSchemaTypePtr *localType,
20895 xmlSchemaElementPtr elemDecl)
20896{
20897 int ret = 0;
20898 /*
20899 * cvc-elt (3.3.4) : (4)
20900 * AND
20901 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20902 * (1.2.1.2.1) - (1.2.1.2.4)
20903 * Handle 'xsi:type'.
20904 */
20905 if (localType == NULL)
20906 return (-1);
20907 *localType = NULL;
20908 if (iattr == NULL)
20909 return (0);
20910 else {
20911 const xmlChar *nsName = NULL, *local = NULL;
20912 /*
20913 * TODO: We should report a *warning* that the type was overriden
20914 * by the instance.
20915 */
20916 ACTIVATE_ATTRIBUTE(iattr);
20917 /*
20918 * (cvc-elt) (3.3.4) : (4.1)
20919 * (cvc-assess-elt) (1.2.1.2.2)
20920 */
20921 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20922 &nsName, &local);
20923 if (ret != 0) {
20924 if (ret < 0) {
20925 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20926 "calling xmlSchemaQNameExpand() to validate the "
20927 "attribute 'xsi:type'");
20928 goto internal_error;
20929 }
20930 goto exit;
20931 }
20932 /*
20933 * (cvc-elt) (3.3.4) : (4.2)
20934 * (cvc-assess-elt) (1.2.1.2.3)
20935 */
20936 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20937 if (*localType == NULL) {
20938 xmlChar *str = NULL;
20939
20940 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20941 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20942 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20943 "The QName value '%s' of the xsi:type attribute does not "
20944 "resolve to a type definition",
20945 xmlSchemaFormatQName(&str, nsName, local), NULL);
20946 FREE_AND_NULL(str);
20947 ret = vctxt->err;
20948 goto exit;
20949 }
20950 if (elemDecl != NULL) {
20951 int set = 0;
20952
20953 /*
20954 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20955 * "The ·local type definition· must be validly
20956 * derived from the {type definition} given the union of
20957 * the {disallowed substitutions} and the {type definition}'s
20958 * {prohibited substitutions}, as defined in
20959 * Type Derivation OK (Complex) (§3.4.6)
20960 * (if it is a complex type definition),
20961 * or given {disallowed substitutions} as defined in Type
20962 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20963 * definition)."
20964 *
20965 * {disallowed substitutions}: the "block" on the element decl.
20966 * {prohibited substitutions}: the "block" on the type def.
20967 */
20968 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
20969 (elemDecl->subtypes->flags &
20970 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
20971 set |= SUBSET_EXTENSION;
20972
20973 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
20974 (elemDecl->subtypes->flags &
20975 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
20976 set |= SUBSET_RESTRICTION;
20977
20978 if (xmlSchemaCheckCOSDerivedOK(*localType,
20979 elemDecl->subtypes, set) != 0) {
20980 xmlChar *str = NULL;
20981
20982 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20983 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
20984 "The type definition '%s', specified by xsi:type, is "
20985 "blocked or not validly derived from the type definition "
20986 "of the element declaration",
20987 xmlSchemaFormatQName(&str,
20988 (*localType)->targetNamespace,
20989 (*localType)->name),
20990 NULL);
20991 FREE_AND_NULL(str);
20992 ret = vctxt->err;
20993 *localType = NULL;
20994 }
20995 }
20996 }
20997exit:
20998 ACTIVATE_ELEM;
20999 return (ret);
21000internal_error:
21001 ACTIVATE_ELEM;
21002 return (-1);
21003}
21004
21005static int
21006xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21007{
21008 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21009 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21010
21011 /*
21012 * cvc-elt (3.3.4) : 1
21013 */
21014 if (elemDecl == NULL) {
21015 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21016 "No matching declaration available");
21017 return (vctxt->err);
21018 }
21019 /*
21020 * cvc-elt (3.3.4) : 2
21021 */
21022 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21023 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21024 "The element declaration is abstract");
21025 return (vctxt->err);
21026 }
21027 if (actualType == NULL) {
21028 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21029 "The type definition is absent");
21030 return (XML_SCHEMAV_CVC_TYPE_1);
21031 }
21032 if (vctxt->nbAttrInfos != 0) {
21033 int ret;
21034 xmlSchemaAttrInfoPtr iattr;
21035 /*
21036 * cvc-elt (3.3.4) : 3
21037 * Handle 'xsi:nil'.
21038 */
21039 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21040 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21041 if (iattr) {
21042 ACTIVATE_ATTRIBUTE(iattr);
21043 /*
21044 * Validate the value.
21045 */
21046 ret = xmlSchemaVCheckCVCSimpleType(
21047 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21048 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21049 iattr->value, &(iattr->val), 1, 0, 0);
21050 ACTIVATE_ELEM;
21051 if (ret < 0) {
21052 VERROR_INT("xmlSchemaValidateElemDecl",
21053 "calling xmlSchemaVCheckCVCSimpleType() to "
21054 "validate the attribute 'xsi:nil'");
21055 return (-1);
21056 }
21057 if (ret == 0) {
21058 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21059 /*
21060 * cvc-elt (3.3.4) : 3.1
21061 */
21062 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21063 "The element is not 'nillable'");
21064 /* Does not return an error on purpose. */
21065 } else {
21066 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21067 /*
21068 * cvc-elt (3.3.4) : 3.2.2
21069 */
21070 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21071 (elemDecl->value != NULL)) {
21072 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21073 "The element cannot be 'nilled' because "
21074 "there is a fixed value constraint defined "
21075 "for it");
21076 /* Does not return an error on purpose. */
21077 } else
21078 vctxt->inode->flags |=
21079 XML_SCHEMA_ELEM_INFO_NILLED;
21080 }
21081 }
21082 }
21083 }
21084 /*
21085 * cvc-elt (3.3.4) : 4
21086 * Handle 'xsi:type'.
21087 */
21088 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21089 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21090 if (iattr) {
21091 xmlSchemaTypePtr localType = NULL;
21092
21093 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21094 elemDecl);
21095 if (ret != 0) {
21096 if (ret == -1) {
21097 VERROR_INT("xmlSchemaValidateElemDecl",
21098 "calling xmlSchemaProcessXSIType() to "
21099 "process the attribute 'xsi:type'");
21100 return (-1);
21101 }
21102 /* Does not return an error on purpose. */
21103 }
21104 if (localType != NULL) {
21105 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21106 actualType = localType;
21107 }
21108 }
21109 }
21110 /*
21111 * IDC: Register identity-constraint XPath matchers.
21112 */
21113 if ((elemDecl->idcs != NULL) &&
21114 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21115 return (-1);
21116 /*
21117 * No actual type definition.
21118 */
21119 if (actualType == NULL) {
21120 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21121 "The type definition is absent");
21122 return (XML_SCHEMAV_CVC_TYPE_1);
21123 }
21124 /*
21125 * Remember the actual type definition.
21126 */
21127 vctxt->inode->typeDef = actualType;
21128
21129 return (0);
21130}
21131
21132static int
21133xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21134{
21135 xmlSchemaAttrInfoPtr iattr;
21136 int ret = 0, i;
21137
21138 /*
21139 * SPEC cvc-type (3.1.1)
21140 * "The attributes of must be empty, excepting those whose namespace
21141 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21142 * whose local name is one of type, nil, schemaLocation or
21143 * noNamespaceSchemaLocation."
21144 */
21145 if (vctxt->nbAttrInfos == 0)
21146 return (0);
21147 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21148 iattr = vctxt->attrInfos[i];
21149 if (! iattr->metaType) {
21150 ACTIVATE_ATTRIBUTE(iattr)
21151 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21152 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21153 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21154 }
21155 }
21156 ACTIVATE_ELEM
21157 return (ret);
21158}
21159
21160/*
21161* Cleanup currently used attribute infos.
21162*/
21163static void
21164xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21165{
21166 int i;
21167 xmlSchemaAttrInfoPtr attr;
21168
21169 if (vctxt->nbAttrInfos == 0)
21170 return;
21171 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21172 attr = vctxt->attrInfos[i];
21173 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21174 if (attr->localName != NULL)
21175 xmlFree((xmlChar *) attr->localName);
21176 if (attr->nsName != NULL)
21177 xmlFree((xmlChar *) attr->nsName);
21178 }
21179 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21180 if (attr->value != NULL)
21181 xmlFree((xmlChar *) attr->value);
21182 }
21183 if (attr->val != NULL) {
21184 xmlSchemaFreeValue(attr->val);
21185 attr->val = NULL;
21186 }
21187 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21188 }
21189 vctxt->nbAttrInfos = 0;
21190}
21191
21192/*
21193* 3.4.4 Complex Type Definition Validation Rules
21194* Element Locally Valid (Complex Type) (cvc-complex-type)
21195* 3.2.4 Attribute Declaration Validation Rules
21196* Validation Rule: Attribute Locally Valid (cvc-attribute)
21197* Attribute Locally Valid (Use) (cvc-au)
21198*
21199* Only "assessed" attribute information items will be visible to
21200* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21201*/
21202static int
21203xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21204{
21205 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21206 xmlSchemaAttributeLinkPtr attrUseLink;
21207 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21208 xmlSchemaAttrInfoPtr attr, tmpAttr;
21209 int i, found, nbAttrs;
21210 int xpathRes = 0, res, wildIDs = 0, fixed;
21211
21212 /*
21213 * SPEC (cvc-attribute)
21214 * (1) "The declaration must not be ·absent· (see Missing
21215 * Sub-components (§5.3) for how this can fail to be
21216 * the case)."
21217 * (2) "Its {type definition} must not be absent."
21218 *
21219 * NOTE (1) + (2): This is not handled here, since we currently do not
21220 * allow validation against schemas which have missing sub-components.
21221 *
21222 * SPEC (cvc-complex-type)
21223 * (3) "For each attribute information item in the element information
21224 * item's [attributes] excepting those whose [namespace name] is
21225 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21226 * [local name] is one of type, nil, schemaLocation or
21227 * noNamespaceSchemaLocation, the appropriate case among the following
21228 * must be true:
21229 *
21230 */
21231 nbAttrs = vctxt->nbAttrInfos;
21232 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21233 attrUseLink = attrUseLink->next) {
21234
21235 found = 0;
21236 attrUse = attrUseLink->attr;
21237 /*
21238 * VAL TODO: Implement a real "attribute use" component.
21239 */
21240 if (attrUse->refDecl != NULL)
21241 attrDecl = attrUse->refDecl;
21242 else
21243 attrDecl = attrUse;
21244 for (i = 0; i < nbAttrs; i++) {
21245 attr = vctxt->attrInfos[i];
21246 /*
21247 * SPEC (cvc-complex-type) (3)
21248 * Skip meta attributes.
21249 */
21250 if (attr->metaType)
21251 continue;
21252 if (attr->localName[0] != attrDecl->name[0])
21253 continue;
21254 if (!xmlStrEqual(attr->localName, attrDecl->name))
21255 continue;
21256 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21257 continue;
21258 found = 1;
21259 /*
21260 * SPEC (cvc-complex-type)
21261 * (3.1) "If there is among the {attribute uses} an attribute
21262 * use with an {attribute declaration} whose {name} matches
21263 * the attribute information item's [local name] and whose
21264 * {target namespace} is identical to the attribute information
21265 * item's [namespace name] (where an ·absent· {target namespace}
21266 * is taken to be identical to a [namespace name] with no value),
21267 * then the attribute information must be ·valid· with respect
21268 * to that attribute use as per Attribute Locally Valid (Use)
21269 * (§3.5.4). In this case the {attribute declaration} of that
21270 * attribute use is the ·context-determined declaration· for the
21271 * attribute information item with respect to Schema-Validity
21272 * Assessment (Attribute) (§3.2.4) and
21273 * Assessment Outcome (Attribute) (§3.2.5).
21274 */
21275 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21276 attr->use = attrUse;
21277 /*
21278 * Context-determined declaration.
21279 */
21280 attr->decl = attrDecl;
21281 attr->typeDef = attrDecl->subtypes;
21282 break;
21283 }
21284
21285 if (found)
21286 continue;
21287
21288 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21289 /*
21290 * Handle non-existent, required attributes.
21291 *
21292 * SPEC (cvc-complex-type)
21293 * (4) "The {attribute declaration} of each attribute use in
21294 * the {attribute uses} whose {required} is true matches one
21295 * of the attribute information items in the element information
21296 * item's [attributes] as per clause 3.1 above."
21297 */
21298 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21299 if (tmpAttr == NULL) {
21300 VERROR_INT(
21301 "xmlSchemaVAttributesComplex",
21302 "calling xmlSchemaGetFreshAttrInfo()");
21303 return (-1);
21304 }
21305 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21306 tmpAttr->use = attrUse;
21307 tmpAttr->decl = attrDecl;
21308 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21309 ((attrUse->defValue != NULL) ||
21310 (attrDecl->defValue != NULL))) {
21311 /*
21312 * Handle non-existent, optional, default/fixed attributes.
21313 */
21314 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21315 if (tmpAttr == NULL) {
21316 VERROR_INT(
21317 "xmlSchemaVAttributesComplex",
21318 "calling xmlSchemaGetFreshAttrInfo()");
21319 return (-1);
21320 }
21321 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21322 tmpAttr->use = attrUse;
21323 tmpAttr->decl = attrDecl;
21324 tmpAttr->typeDef = attrDecl->subtypes;
21325 tmpAttr->localName = attrDecl->name;
21326 tmpAttr->nsName = attrDecl->targetNamespace;
21327 }
21328 }
21329 if (vctxt->nbAttrInfos == 0)
21330 return (0);
21331 /*
21332 * Validate against the wildcard.
21333 */
21334 if (type->attributeWildcard != NULL) {
21335 /*
21336 * SPEC (cvc-complex-type)
21337 * (3.2.1) "There must be an {attribute wildcard}."
21338 */
21339 for (i = 0; i < nbAttrs; i++) {
21340 attr = vctxt->attrInfos[i];
21341 /*
21342 * SPEC (cvc-complex-type) (3)
21343 * Skip meta attributes.
21344 */
21345 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21346 continue;
21347 /*
21348 * SPEC (cvc-complex-type)
21349 * (3.2.2) "The attribute information item must be ·valid· with
21350 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21351 *
21352 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21353 * "... its [namespace name] must be ·valid· with respect to
21354 * the wildcard constraint, as defined in Wildcard allows
21355 * Namespace Name (§3.10.4)."
21356 */
21357 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21358 attr->nsName)) {
21359 /*
21360 * Handle processContents.
21361 *
21362 * SPEC (cvc-wildcard):
21363 * processContents | context-determined declaration:
21364 * "strict" "mustFind"
21365 * "lax" "none"
21366 * "skip" "skip"
21367 */
21368 if (type->attributeWildcard->processContents ==
21369 XML_SCHEMAS_ANY_SKIP) {
21370 /*
21371 * context-determined declaration = "skip"
21372 *
21373 * SPEC PSVI Assessment Outcome (Attribute)
21374 * [validity] = "notKnown"
21375 * [validation attempted] = "none"
21376 */
21377 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21378 continue;
21379 }
21380 /*
21381 * Find an attribute declaration.
21382 */
21383 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21384 attr->localName, attr->nsName);
21385 if (attr->decl != NULL) {
21386 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21387 /*
21388 * SPEC (cvc-complex-type)
21389 * (5) "Let [Definition:] the wild IDs be the set of
21390 * all attribute information item to which clause 3.2
21391 * applied and whose ·validation· resulted in a
21392 * ·context-determined declaration· of mustFind or no
21393 * ·context-determined declaration· at all, and whose
21394 * [local name] and [namespace name] resolve (as
21395 * defined by QName resolution (Instance) (§3.15.4)) to
21396 * an attribute declaration whose {type definition} is
21397 * or is derived from ID. Then all of the following
21398 * must be true:"
21399 */
21400 attr->typeDef = attr->decl->subtypes;
21401 if (xmlSchemaIsDerivedFromBuiltInType(
21402 attr->typeDef, XML_SCHEMAS_ID)) {
21403 /*
21404 * SPEC (5.1) "There must be no more than one
21405 * item in ·wild IDs·."
21406 */
21407 if (wildIDs != 0) {
21408 /* VAL TODO */
21409 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21410 TODO
21411 continue;
21412 }
21413 wildIDs++;
21414 /*
21415 * SPEC (cvc-complex-type)
21416 * (5.2) "If ·wild IDs· is non-empty, there must not
21417 * be any attribute uses among the {attribute uses}
21418 * whose {attribute declaration}'s {type definition}
21419 * is or is derived from ID."
21420 */
21421 for (attrUseLink = type->attributeUses;
21422 attrUseLink != NULL;
21423 attrUseLink = attrUseLink->next) {
21424 if (xmlSchemaIsDerivedFromBuiltInType(
21425 attrUseLink->attr->subtypes,
21426 XML_SCHEMAS_ID)) {
21427 /* VAL TODO */
21428 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21429 TODO
21430 }
21431 }
21432 }
21433 } else if (type->attributeWildcard->processContents ==
21434 XML_SCHEMAS_ANY_LAX) {
21435 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21436 /*
21437 * SPEC PSVI Assessment Outcome (Attribute)
21438 * [validity] = "notKnown"
21439 * [validation attempted] = "none"
21440 */
21441 } else {
21442 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21443 }
21444 }
21445 }
21446 }
21447
21448
21449 if (vctxt->nbAttrInfos == 0)
21450 return (0);
21451
21452 /*
21453 * Validate values, create default attributes, evaluate IDCs.
21454 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021455 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21456 attr = vctxt->attrInfos[i];
21457 /*
21458 * VAL TODO: Note that we won't try to resolve IDCs to
21459 * "lax" and "skip" validated attributes. Check what to
21460 * do in this case.
21461 */
21462 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21463 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21464 continue;
21465 /*
21466 * VAL TODO: What to do if the type definition is missing?
21467 */
21468 if (attr->typeDef == NULL) {
21469 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21470 continue;
21471 }
21472
21473 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021474 fixed = 0;
21475 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021476
21477 if (vctxt->xpathStates != NULL) {
21478 /*
21479 * Evaluate IDCs.
21480 */
21481 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21482 XML_ATTRIBUTE_NODE);
21483 if (xpathRes == -1) {
21484 VERROR_INT("xmlSchemaVAttributesComplex",
21485 "calling xmlSchemaXPathEvaluate()");
21486 goto internal_error;
21487 }
21488 }
21489
21490 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21491 /*
21492 * Default/fixed attributes.
21493 */
21494 if (xpathRes) {
21495 if (attr->use->defValue == NULL) {
21496 attr->value = (xmlChar *) attr->use->defValue;
21497 attr->val = attr->use->defVal;
21498 } else {
21499 attr->value = (xmlChar *) attr->decl->defValue;
21500 attr->val = attr->decl->defVal;
21501 }
21502 /*
21503 * IDCs will consume the precomputed default value,
21504 * so we need to clone it.
21505 */
21506 if (attr->val == NULL) {
21507 VERROR_INT("xmlSchemaVAttributesComplex",
21508 "default/fixed value on an attribute use was "
21509 "not precomputed");
21510 goto internal_error;
21511 }
21512 attr->val = xmlSchemaCopyValue(attr->val);
21513 if (attr->val == NULL) {
21514 VERROR_INT("xmlSchemaVAttributesComplex",
21515 "calling xmlSchemaCopyValue()");
21516 goto internal_error;
21517 }
21518 }
21519 /*
21520 * PSVI: Add the default attribute to the current element.
21521 * VAL TODO: Should we use the *normalized* value? This currently
21522 * uses the *initial* value.
21523 */
21524 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21525 (attr->node != NULL) && (attr->node->doc != NULL)) {
21526 xmlChar *normValue;
21527 const xmlChar *value;
21528
21529 value = attr->value;
21530 /*
21531 * Normalize the value.
21532 */
21533 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21534 attr->value);
21535 if (normValue != NULL)
21536 value = BAD_CAST normValue;
21537
21538 if (attr->nsName == NULL) {
21539 if (xmlNewProp(attr->node->parent,
21540 attr->localName, value) == NULL) {
21541 VERROR_INT("xmlSchemaVAttributesComplex",
21542 "callling xmlNewProp()");
21543 if (normValue != NULL)
21544 xmlFree(normValue);
21545 goto internal_error;
21546 }
21547 } else {
21548 xmlNsPtr ns;
21549
21550 ns = xmlSearchNsByHref(attr->node->doc,
21551 attr->node->parent, attr->nsName);
21552 if (ns == NULL) {
21553 xmlChar prefix[12];
21554 int counter = 0;
21555
21556 /*
21557 * Create a namespace declaration on the validation
21558 * root node if no namespace declaration is in scope.
21559 */
21560 do {
21561 snprintf((char *) prefix, 12, "p%d", counter++);
21562 ns = xmlSearchNs(attr->node->doc,
21563 attr->node->parent, BAD_CAST prefix);
21564 if (counter > 1000) {
21565 VERROR_INT(
21566 "xmlSchemaVAttributesComplex",
21567 "could not compute a ns prefix for a "
21568 "default/fixed attribute");
21569 if (normValue != NULL)
21570 xmlFree(normValue);
21571 goto internal_error;
21572 }
21573 } while (ns != NULL);
21574 ns = xmlNewNs(vctxt->validationRoot,
21575 attr->nsName, BAD_CAST prefix);
21576 }
21577 xmlNewNsProp(attr->node->parent, ns,
21578 attr->localName, value);
21579 }
21580 if (normValue != NULL)
21581 xmlFree(normValue);
21582 }
21583 /*
21584 * Go directly to IDC evaluation.
21585 */
21586 goto eval_idcs;
21587 }
21588 /*
21589 * Validate the value.
21590 */
21591 if (vctxt->value != NULL) {
21592 /*
21593 * Free last computed value; just for safety reasons.
21594 */
21595 xmlSchemaFreeValue(vctxt->value);
21596 vctxt->value = NULL;
21597 }
21598 /*
21599 * Note that the attribute *use* can be unavailable, if
21600 * the attribute was a wild attribute.
21601 */
21602 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21603 ((attr->use != NULL) &&
21604 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21605 fixed = 1;
21606 else
21607 fixed = 0;
21608 /*
21609 * SPEC (cvc-attribute)
21610 * (3) "The item's ·normalized value· must be locally ·valid·
21611 * with respect to that {type definition} as per
21612 * String Valid (§3.14.4)."
21613 *
21614 * VAL TODO: Do we already have the
21615 * "normalized attribute value" here?
21616 */
21617 if (xpathRes || fixed) {
21618 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21619 /*
21620 * Request a computed value.
21621 */
21622 res = xmlSchemaVCheckCVCSimpleType(
21623 (xmlSchemaAbstractCtxtPtr) vctxt,
21624 attr->node, attr->typeDef, attr->value, &(attr->val),
21625 1, 1, 0);
21626 } else {
21627 res = xmlSchemaVCheckCVCSimpleType(
21628 (xmlSchemaAbstractCtxtPtr) vctxt,
21629 attr->node, attr->typeDef, attr->value, NULL,
21630 1, 0, 0);
21631 }
21632
21633 if (res != 0) {
21634 if (res == -1) {
21635 VERROR_INT("xmlSchemaVAttributesComplex",
21636 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21637 goto internal_error;
21638 }
21639 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21640 /*
21641 * SPEC PSVI Assessment Outcome (Attribute)
21642 * [validity] = "invalid"
21643 */
21644 goto eval_idcs;
21645 }
21646
21647 if (fixed) {
21648 int ws;
21649 /*
21650 * SPEC Attribute Locally Valid (Use) (cvc-au)
21651 * "For an attribute information item to be·valid·
21652 * with respect to an attribute use its *normalized*
21653 * value· must match the *canonical* lexical
21654 * representation of the attribute use's {value
21655 * constraint}value, if it is present and fixed."
21656 *
21657 * VAL TODO: The requirement for the *canonical* value
21658 * will be removed in XML Schema 1.1.
21659 */
21660 /*
21661 * SPEC Attribute Locally Valid (cvc-attribute)
21662 * (4) "The item's *actual* value· must match the *value* of
21663 * the {value constraint}, if it is present and fixed."
21664 */
21665 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21666 if (attr->val == NULL) {
21667 /* VAL TODO: A value was not precomputed. */
21668 TODO
21669 goto eval_idcs;
21670 }
21671 if ((attr->use != NULL) &&
21672 (attr->use->defValue != NULL)) {
21673 if (attr->use->defVal == NULL) {
21674 /* VAL TODO: A default value was not precomputed. */
21675 TODO
21676 goto eval_idcs;
21677 }
21678 attr->vcValue = attr->use->defValue;
21679 /*
21680 if (xmlSchemaCompareValuesWhtsp(attr->val,
21681 (xmlSchemaWhitespaceValueType) ws,
21682 attr->use->defVal,
21683 (xmlSchemaWhitespaceValueType) ws) != 0) {
21684 */
21685 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21686 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21687 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021688 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021689 /* VAL TODO: A default value was not precomputed. */
21690 TODO
21691 goto eval_idcs;
21692 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021693 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021694 /*
21695 if (xmlSchemaCompareValuesWhtsp(attr->val,
21696 (xmlSchemaWhitespaceValueType) ws,
21697 attrDecl->defVal,
21698 (xmlSchemaWhitespaceValueType) ws) != 0) {
21699 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021700 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021701 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21702 }
21703 /*
21704 * [validity] = "valid"
21705 */
21706 }
21707eval_idcs:
21708 /*
21709 * Evaluate IDCs.
21710 */
21711 if (xpathRes) {
21712 if (xmlSchemaXPathProcessHistory(vctxt,
21713 vctxt->depth +1) == -1) {
21714 VERROR_INT("xmlSchemaVAttributesComplex",
21715 "calling xmlSchemaXPathEvaluate()");
21716 goto internal_error;
21717 }
21718 }
21719 }
21720
21721 /*
21722 * Report errors.
21723 */
21724 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21725 attr = vctxt->attrInfos[i];
21726 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21727 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21728 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21729 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21730 continue;
21731 ACTIVATE_ATTRIBUTE(attr);
21732 switch (attr->state) {
21733 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21734 xmlChar *str = NULL;
21735 ACTIVATE_ELEM;
21736 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21737 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21738 "The attribute '%s' is required but missing",
21739 xmlSchemaFormatQName(&str,
21740 attr->decl->targetNamespace,
21741 attr->decl->name),
21742 NULL);
21743 FREE_AND_NULL(str)
21744 break;
21745 }
21746 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21747 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21748 "The type definition is absent");
21749 break;
21750 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21751 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21752 XML_SCHEMAV_CVC_AU, NULL, NULL,
21753 "The value '%s' does not match the fixed "
21754 "value constraint '%s'",
21755 attr->value, attr->vcValue);
21756 break;
21757 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21758 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21759 "No matching global attribute declaration available, but "
21760 "demanded by the strict wildcard");
21761 break;
21762 case XML_SCHEMAS_ATTR_UNKNOWN:
21763 if (attr->metaType)
21764 break;
21765 /*
21766 * MAYBE VAL TODO: One might report different error messages
21767 * for the following errors.
21768 */
21769 if (type->attributeWildcard == NULL) {
21770 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21771 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21772 } else {
21773 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21774 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21775 }
21776 break;
21777 default:
21778 break;
21779 }
21780 }
21781
21782 ACTIVATE_ELEM;
21783 return (0);
21784internal_error:
21785 ACTIVATE_ELEM;
21786 return (-1);
21787}
21788
21789static int
21790xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21791 int *skip)
21792{
21793 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21794 /*
21795 * The namespace of the element was already identified to be
21796 * matching the wildcard.
21797 */
21798 if ((skip == NULL) || (wild == NULL) ||
21799 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21800 VERROR_INT("xmlSchemaValidateElemWildcard",
21801 "bad arguments");
21802 return (-1);
21803 }
21804 *skip = 0;
21805 if (wild->negNsSet != NULL) {
21806 /*
21807 * URGENT VAL TODO: Fix the content model to reject
21808 * "##other" wildcards.
21809 */
21810 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21811 vctxt->inode->nsName) != 0) {
21812 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21813 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21814 /*
21815 * VAL TODO: Workaround possible *only* if minOccurs and
21816 * maxOccurs are 1.
21817 */
21818 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21819 /* VAL TODO: error code? */
21820 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21821 (xmlSchemaTypePtr) wild,
21822 "This element is not accepted by the wildcard",
21823 0, 0, NULL);
21824 vctxt->skipDepth = vctxt->depth;
21825 if ((pinode->flags &
21826 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21827 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21828 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21829 return (XML_SCHEMAV_ELEMENT_CONTENT);
21830 }
21831 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21832 *skip = 1;
21833 return (0);
21834 }
21835 vctxt->inode->typeDef =
21836 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21837 return (0);
21838 }
21839 }
21840 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21841 /*
21842 * URGENT VAL TODO: Either we need to position the stream to the
21843 * next sibling, or walk the whole subtree.
21844 */
21845 *skip = 1;
21846 return (0);
21847 }
21848 {
21849 xmlSchemaElementPtr decl = NULL;
21850
21851 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21852 vctxt->inode->localName, vctxt->inode->nsName,
21853 NULL);
21854 if (decl != NULL) {
21855 vctxt->inode->decl = decl;
21856 return (0);
21857 }
21858 }
21859 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21860 /* VAL TODO: Change to proper error code. */
21861 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21862 "No matching global element declaration available, but "
21863 "demanded by the strict wildcard");
21864 return (vctxt->err);
21865 }
21866 if (vctxt->nbAttrInfos != 0) {
21867 xmlSchemaAttrInfoPtr iattr;
21868 /*
21869 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21870 * (1.2.1.2.1) - (1.2.1.2.3 )
21871 *
21872 * Use the xsi:type attribute for the type definition.
21873 */
21874 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21875 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21876 if (iattr != NULL) {
21877 if (xmlSchemaProcessXSIType(vctxt, iattr,
21878 &(vctxt->inode->typeDef), NULL) == -1) {
21879 VERROR_INT("xmlSchemaValidateElemWildcard",
21880 "calling xmlSchemaProcessXSIType() to "
21881 "process the attribute 'xsi:nil'");
21882 return (-1);
21883 }
21884 /*
21885 * Don't return an error on purpose.
21886 */
21887 return (0);
21888 }
21889 }
21890 /*
21891 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21892 *
21893 * Fallback to "anyType".
21894 */
21895 vctxt->inode->typeDef =
21896 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21897 return (0);
21898}
21899
21900/*
21901* xmlSchemaCheckCOSValidDefault:
21902*
21903* This will be called if: not nilled, no content and a default/fixed
21904* value is provided.
21905*/
21906
21907static int
21908xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21909 const xmlChar *value,
21910 xmlSchemaValPtr *val)
21911{
21912 int ret = 0;
21913 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21914
21915 /*
21916 * cos-valid-default:
21917 * Schema Component Constraint: Element Default Valid (Immediate)
21918 * For a string to be a valid default with respect to a type
21919 * definition the appropriate case among the following must be true:
21920 */
21921 if IS_COMPLEX_TYPE(inode->typeDef) {
21922 /*
21923 * Complex type.
21924 *
21925 * SPEC (2.1) "its {content type} must be a simple type definition
21926 * or mixed."
21927 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21928 * type}'s particle must be ·emptiable· as defined by
21929 * Particle Emptiable (§3.9.6)."
21930 */
21931 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21932 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21933 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21934 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21935 /* NOTE that this covers (2.2.2) as well. */
21936 VERROR(ret, NULL,
21937 "For a string to be a valid default, the type definition "
21938 "must be a simple type or a complex type with simple content "
21939 "or mixed content and a particle emptiable");
21940 return(ret);
21941 }
21942 }
21943 /*
21944 * 1 If the type definition is a simple type definition, then the string
21945 * must be ·valid· with respect to that definition as defined by String
21946 * Valid (§3.14.4).
21947 *
21948 * AND
21949 *
21950 * 2.2.1 If the {content type} is a simple type definition, then the
21951 * string must be ·valid· with respect to that simple type definition
21952 * as defined by String Valid (§3.14.4).
21953 */
21954 if (IS_SIMPLE_TYPE(inode->typeDef)) {
21955
21956 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21957 NULL, inode->typeDef, value, val, 1, 1, 0);
21958
21959 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
21960
21961 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21962 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
21963 }
21964 if (ret < 0) {
21965 VERROR_INT("xmlSchemaCheckCOSValidDefault",
21966 "calling xmlSchemaVCheckCVCSimpleType()");
21967 }
21968 return (ret);
21969}
21970
21971static void
21972xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21973 const xmlChar * name ATTRIBUTE_UNUSED,
21974 xmlSchemaElementPtr item,
21975 xmlSchemaNodeInfoPtr inode)
21976{
21977 inode->decl = item;
21978#ifdef DEBUG_CONTENT
21979 {
21980 xmlChar *str = NULL;
21981
21982 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
21983 xmlGenericError(xmlGenericErrorContext,
21984 "AUTOMATON callback for '%s' [declaration]\n",
21985 xmlSchemaFormatQName(&str,
21986 inode->localName, inode->nsName));
21987 } else {
21988 xmlGenericError(xmlGenericErrorContext,
21989 "AUTOMATON callback for '%s' [wildcard]\n",
21990 xmlSchemaFormatQName(&str,
21991 inode->localName, inode->nsName));
21992
21993 }
21994 FREE_AND_NULL(str)
21995 }
21996#endif
21997}
21998
21999static int
22000xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022001{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022002 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22003 if (vctxt->inode == NULL) {
22004 VERROR_INT("xmlSchemaValidatorPushElem",
22005 "calling xmlSchemaGetFreshElemInfo()");
22006 return (-1);
22007 }
22008 vctxt->nbAttrInfos = 0;
22009 return (0);
22010}
22011
22012static int
22013xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22014 xmlSchemaNodeInfoPtr inode,
22015 xmlSchemaTypePtr type,
22016 const xmlChar *value)
22017{
22018 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22019 return (xmlSchemaVCheckCVCSimpleType(
22020 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22021 type, value, &(inode->val), 1, 1, 0));
22022 else
22023 return (xmlSchemaVCheckCVCSimpleType(
22024 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22025 type, value, NULL, 1, 0, 0));
22026}
22027
22028
22029
22030/*
22031* Process END of element.
22032*/
22033static int
22034xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22035{
22036 int ret = 0;
22037 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22038
22039 if (vctxt->nbAttrInfos != 0)
22040 xmlSchemaClearAttrInfos(vctxt);
22041 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22042 /*
22043 * This element was not expected;
22044 * we will not validate child elements of broken parents.
22045 * Skip validation of all content of the parent.
22046 */
22047 vctxt->skipDepth = vctxt->depth -1;
22048 goto end_elem;
22049 }
22050 if ((inode->typeDef == NULL) ||
22051 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22052 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022053 * 1. the type definition might be missing if the element was
22054 * error prone
22055 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022056 */
22057 goto end_elem;
22058 }
22059 /*
22060 * Check the content model.
22061 */
22062 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22063 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22064
22065 /*
22066 * Workaround for "anyType".
22067 */
22068 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22069 goto character_content;
22070
22071 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22072 xmlChar *values[10];
22073 int terminal, nbval = 10, nbneg;
22074
22075 if (inode->regexCtxt == NULL) {
22076 /*
22077 * Create the regex context.
22078 */
22079 inode->regexCtxt =
22080 xmlRegNewExecCtxt(inode->typeDef->contModel,
22081 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22082 vctxt);
22083 if (inode->regexCtxt == NULL) {
22084 VERROR_INT("xmlSchemaValidatorPopElem",
22085 "failed to create a regex context");
22086 goto internal_error;
22087 }
22088#ifdef DEBUG_AUTOMATA
22089 xmlGenericError(xmlGenericErrorContext,
22090 "AUTOMATON create on '%s'\n", inode->localName);
22091#endif
22092 }
22093 /*
22094 * Get hold of the still expected content, since a further
22095 * call to xmlRegExecPushString() will loose this information.
22096 */
22097 xmlRegExecNextValues(inode->regexCtxt,
22098 &nbval, &nbneg, &values[0], &terminal);
22099 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22100 if (ret <= 0) {
22101 /*
22102 * Still missing something.
22103 */
22104 ret = 1;
22105 inode->flags |=
22106 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22107 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22108 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22109 "Missing child element(s)",
22110 nbval, nbneg, values);
22111#ifdef DEBUG_AUTOMATA
22112 xmlGenericError(xmlGenericErrorContext,
22113 "AUTOMATON missing ERROR on '%s'\n",
22114 inode->localName);
22115#endif
22116 } else {
22117 /*
22118 * Content model is satisfied.
22119 */
22120 ret = 0;
22121#ifdef DEBUG_AUTOMATA
22122 xmlGenericError(xmlGenericErrorContext,
22123 "AUTOMATON succeeded on '%s'\n",
22124 inode->localName);
22125#endif
22126 }
22127
22128 }
22129 }
22130 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22131 goto end_elem;
22132
22133character_content:
22134
22135 if (vctxt->value != NULL) {
22136 xmlSchemaFreeValue(vctxt->value);
22137 vctxt->value = NULL;
22138 }
22139 /*
22140 * Check character content.
22141 */
22142 if (inode->decl == NULL) {
22143 /*
22144 * Speedup if no declaration exists.
22145 */
22146 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22147 ret = xmlSchemaVCheckINodeDataType(vctxt,
22148 inode, inode->typeDef, inode->value);
22149 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22150 ret = xmlSchemaVCheckINodeDataType(vctxt,
22151 inode, inode->typeDef->contentTypeDef,
22152 inode->value);
22153 }
22154 if (ret < 0) {
22155 VERROR_INT("xmlSchemaValidatorPopElem",
22156 "calling xmlSchemaVCheckCVCSimpleType()");
22157 goto internal_error;
22158 }
22159 goto end_elem;
22160 }
22161 /*
22162 * cvc-elt (3.3.4) : 5
22163 * The appropriate case among the following must be true:
22164 */
22165 /*
22166 * cvc-elt (3.3.4) : 5.1
22167 * If the declaration has a {value constraint},
22168 * the item has neither element nor character [children] and
22169 * clause 3.2 has not applied, then all of the following must be true:
22170 */
22171 if ((inode->decl->value != NULL) &&
22172 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22173 (! INODE_NILLED(inode))) {
22174 /*
22175 * cvc-elt (3.3.4) : 5.1.1
22176 * If the ·actual type definition· is a ·local type definition·
22177 * then the canonical lexical representation of the {value constraint}
22178 * value must be a valid default for the ·actual type definition· as
22179 * defined in Element Default Valid (Immediate) (§3.3.6).
22180 */
22181 /*
22182 * NOTE: 'local' above means types aquired by xsi:type.
22183 * NOTE: Although the *canonical* value is stated, it is not
22184 * relevant if canonical or not. Additionally XML Schema 1.1
22185 * will removed this requirement as well.
22186 */
22187 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22188
22189 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22190 inode->decl->value, &(inode->val));
22191 if (ret != 0) {
22192 if (ret < 0) {
22193 VERROR_INT("xmlSchemaValidatorPopElem",
22194 "calling xmlSchemaCheckCOSValidDefault()");
22195 goto internal_error;
22196 }
22197 goto end_elem;
22198 }
22199 /*
22200 * Stop here, to avoid redundant validation of the value
22201 * (see following).
22202 */
22203 goto default_psvi;
22204 }
22205 /*
22206 * cvc-elt (3.3.4) : 5.1.2
22207 * The element information item with the canonical lexical
22208 * representation of the {value constraint} value used as its
22209 * ·normalized value· must be ·valid· with respect to the
22210 * ·actual type definition· as defined by Element Locally Valid (Type)
22211 * (§3.3.4).
22212 */
22213 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22214 ret = xmlSchemaVCheckINodeDataType(vctxt,
22215 inode, inode->typeDef, inode->decl->value);
22216 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22217 ret = xmlSchemaVCheckINodeDataType(vctxt,
22218 inode, inode->typeDef->contentTypeDef,
22219 inode->decl->value);
22220 }
22221 if (ret != 0) {
22222 if (ret < 0) {
22223 VERROR_INT("xmlSchemaValidatorPopElem",
22224 "calling xmlSchemaVCheckCVCSimpleType()");
22225 goto internal_error;
22226 }
22227 goto end_elem;
22228 }
22229
22230default_psvi:
22231 /*
22232 * PSVI: Create a text node on the instance element.
22233 */
22234 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22235 (inode->node != NULL)) {
22236 xmlNodePtr textChild;
22237 xmlChar *normValue;
22238 /*
22239 * VAL TODO: Normalize the value.
22240 */
22241 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22242 inode->decl->value);
22243 if (normValue != NULL) {
22244 textChild = xmlNewText(BAD_CAST normValue);
22245 xmlFree(normValue);
22246 } else
22247 textChild = xmlNewText(inode->decl->value);
22248 if (textChild == NULL) {
22249 VERROR_INT("xmlSchemaValidatorPopElem",
22250 "calling xmlNewText()");
22251 goto internal_error;
22252 } else
22253 xmlAddChild(inode->node, textChild);
22254 }
22255
22256 } else if (! INODE_NILLED(inode)) {
22257 /*
22258 * 5.2.1 The element information item must be ·valid· with respect
22259 * to the ·actual type definition· as defined by Element Locally
22260 * Valid (Type) (§3.3.4).
22261 */
22262 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22263 /*
22264 * SPEC (cvc-type) (3.1)
22265 * "If the type definition is a simple type definition, ..."
22266 * (3.1.3) "If clause 3.2 of Element Locally Valid
22267 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22268 * must be ·valid· with respect to the type definition as defined
22269 * by String Valid (§3.14.4).
22270 */
22271 ret = xmlSchemaVCheckINodeDataType(vctxt,
22272 inode, inode->typeDef, inode->value);
22273 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22274 /*
22275 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22276 * definition, then the element information item must be
22277 * ·valid· with respect to the type definition as per
22278 * Element Locally Valid (Complex Type) (§3.4.4);"
22279 *
22280 * SPEC (cvc-complex-type) (2.2)
22281 * "If the {content type} is a simple type definition, ...
22282 * the ·normalized value· of the element information item is
22283 * ·valid· with respect to that simple type definition as
22284 * defined by String Valid (§3.14.4)."
22285 */
22286 ret = xmlSchemaVCheckINodeDataType(vctxt,
22287 inode, inode->typeDef->contentTypeDef, inode->value);
22288 }
22289 if (ret != 0) {
22290 if (ret < 0) {
22291 VERROR_INT("xmlSchemaValidatorPopElem",
22292 "calling xmlSchemaVCheckCVCSimpleType()");
22293 goto internal_error;
22294 }
22295 goto end_elem;
22296 }
22297 /*
22298 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22299 * not applied, all of the following must be true:
22300 */
22301 if ((inode->decl->value != NULL) &&
22302 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22303
22304 /*
22305 * TODO: We will need a computed value, when comparison is
22306 * done on computed values.
22307 */
22308 /*
22309 * 5.2.2.1 The element information item must have no element
22310 * information item [children].
22311 */
22312 if (inode->flags &
22313 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22314 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22315 VERROR(ret, NULL,
22316 "The content must not containt element nodes since "
22317 "there is a fixed value constraint");
22318 goto end_elem;
22319 } else {
22320 /*
22321 * 5.2.2.2 The appropriate case among the following must
22322 * be true:
22323 */
22324 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22325 /*
22326 * 5.2.2.2.1 If the {content type} of the ·actual type
22327 * definition· is mixed, then the *initial value* of the
22328 * item must match the canonical lexical representation
22329 * of the {value constraint} value.
22330 *
22331 * ... the *initial value* of an element information
22332 * item is the string composed of, in order, the
22333 * [character code] of each character information item in
22334 * the [children] of that element information item.
22335 */
22336 if (! xmlStrEqual(inode->value, inode->decl->value)){
22337 /*
22338 * VAL TODO: Report invalid & expected values as well.
22339 * VAL TODO: Implement the canonical stuff.
22340 */
22341 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22342 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22343 ret, NULL, NULL,
22344 "The initial value '%s' does not match the fixed "
22345 "value constraint '%s'",
22346 inode->value, inode->decl->value);
22347 goto end_elem;
22348 }
22349 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22350 /*
22351 * 5.2.2.2.2 If the {content type} of the ·actual type
22352 * definition· is a simple type definition, then the
22353 * *actual value* of the item must match the canonical
22354 * lexical representation of the {value constraint} value.
22355 */
22356 /*
22357 * VAL TODO: *actual value* is the normalized value, impl.
22358 * this.
22359 * VAL TODO: Report invalid & expected values as well.
22360 * VAL TODO: Implement a comparison with the computed values.
22361 */
22362 if (! xmlStrEqual(inode->value,
22363 inode->decl->value)) {
22364 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22365 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22366 ret, NULL, NULL,
22367 "The actual value '%s' does not match the fixed "
22368 "value constraint '%s'",
22369 inode->value,
22370 inode->decl->value);
22371 goto end_elem;
22372 }
22373 }
22374 }
22375 }
22376 }
22377
22378end_elem:
22379 if (vctxt->depth < 0) {
22380 /* TODO: raise error? */
22381 return (0);
22382 }
22383 if (vctxt->depth == vctxt->skipDepth)
22384 vctxt->skipDepth = -1;
22385 /*
22386 * Evaluate the history of XPath state objects.
22387 */
22388 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22389 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022390 /*
22391 * TODO: 6 The element information item must be ·valid· with respect to each of
22392 * the {identity-constraint definitions} as per Identity-constraint
22393 * Satisfied (§3.11.4).
22394 */
22395 /*
22396 * Validate IDC keyrefs.
22397 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022398 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22399 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022400 /*
22401 * Merge/free the IDC table.
22402 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022403 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022404#ifdef DEBUG_IDC
22405 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022406 inode->nsName,
22407 inode->localName,
22408 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022409#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022410 if (vctxt->depth > 0) {
22411 /*
22412 * Merge the IDC node table with the table of the parent node.
22413 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022414 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22415 goto internal_error;
22416 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022417 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022418 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022419 * Clear the current ielem.
22420 * VAL TODO: Don't free the PSVI IDC tables if they are
22421 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022422 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022423 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022424 /*
22425 * Skip further processing if we are on the validation root.
22426 */
22427 if (vctxt->depth == 0) {
22428 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022429 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022430 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022431 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022432 /*
22433 * Reset the bubbleDepth if needed.
22434 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022435 if (vctxt->aidcs != NULL) {
22436 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22437 do {
22438 if (aidc->bubbleDepth == vctxt->depth) {
22439 /*
22440 * A bubbleDepth of a key/unique IDC matches the current
22441 * depth, this means that we are leaving the scope of the
22442 * top-most keyref IDC.
22443 */
22444 aidc->bubbleDepth = -1;
22445 }
22446 aidc = aidc->next;
22447 } while (aidc != NULL);
22448 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022449 vctxt->depth--;
22450 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022451 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022452 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022453 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22454 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022455 return (ret);
22456
22457internal_error:
22458 vctxt->err = -1;
22459 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022460}
22461
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022462/*
22463* 3.4.4 Complex Type Definition Validation Rules
22464* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22465*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022466static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022467xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022468{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022469 xmlSchemaNodeInfoPtr pielem;
22470 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022471 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022472
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022473 if (vctxt->depth <= 0) {
22474 VERROR_INT("xmlSchemaValidateChildElem",
22475 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022476 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022477 }
22478 pielem = vctxt->elemInfos[vctxt->depth -1];
22479 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22480 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022481 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022482 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022483 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022484 if (INODE_NILLED(pielem)) {
22485 /*
22486 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22487 */
22488 ACTIVATE_PARENT_ELEM;
22489 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22490 VERROR(ret, NULL,
22491 "Neither character nor element content is allowed, "
22492 "because the element was 'nilled'");
22493 ACTIVATE_ELEM;
22494 goto unexpected_elem;
22495 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022496
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022497 ptype = pielem->typeDef;
22498
22499 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22500 /*
22501 * Workaround for "anyType": we have currently no content model
22502 * assigned for "anyType", so handle it explicitely.
22503 * "anyType" has an unbounded, lax "any" wildcard.
22504 */
22505 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22506 vctxt->inode->localName,
22507 vctxt->inode->nsName);
22508
22509 if (vctxt->inode->decl == NULL) {
22510 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022511 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022512 * Process "xsi:type".
22513 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022514 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022515 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22516 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22517 if (iattr != NULL) {
22518 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22519 &(vctxt->inode->typeDef), NULL);
22520 if (ret != 0) {
22521 if (ret == -1) {
22522 VERROR_INT("xmlSchemaValidateChildElem",
22523 "calling xmlSchemaProcessXSIType() to "
22524 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022525 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022526 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022527 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022528 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022529 } else {
22530 /*
22531 * Fallback to "anyType".
22532 *
22533 * SPEC (cvc-assess-elt)
22534 * "If the item cannot be ·strictly assessed·, [...]
22535 * an element information item's schema validity may be laxly
22536 * assessed if its ·context-determined declaration· is not
22537 * skip by ·validating· with respect to the ·ur-type
22538 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22539 */
22540 vctxt->inode->typeDef =
22541 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022542 }
22543 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022544 return (0);
22545 }
22546
22547 switch (ptype->contentType) {
22548 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022549 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022550 * SPEC (2.1) "If the {content type} is empty, then the
22551 * element information item has no character or element
22552 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022553 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022554 ACTIVATE_PARENT_ELEM
22555 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22556 VERROR(ret, NULL,
22557 "Element content is not allowed, "
22558 "because the content type is empty");
22559 ACTIVATE_ELEM
22560 goto unexpected_elem;
22561 break;
22562
22563 case XML_SCHEMA_CONTENT_MIXED:
22564 case XML_SCHEMA_CONTENT_ELEMENTS: {
22565 xmlRegExecCtxtPtr regexCtxt;
22566 xmlChar *values[10];
22567 int terminal, nbval = 10, nbneg;
22568
22569 /* VAL TODO: Optimized "anyType" validation.*/
22570
22571 if (ptype->contModel == NULL) {
22572 VERROR_INT("xmlSchemaValidateChildElem",
22573 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022574 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022575 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022576 /*
22577 * Safety belf for evaluation if the cont. model was already
22578 * examined to be invalid.
22579 */
22580 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22581 VERROR_INT("xmlSchemaValidateChildElem",
22582 "validating elem, but elem content is already invalid");
22583 return (-1);
22584 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022585
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022586 regexCtxt = pielem->regexCtxt;
22587 if (regexCtxt == NULL) {
22588 /*
22589 * Create the regex context.
22590 */
22591 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22592 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22593 vctxt);
22594 if (regexCtxt == NULL) {
22595 VERROR_INT("xmlSchemaValidateChildElem",
22596 "failed to create a regex context");
22597 return (-1);
22598 }
22599 pielem->regexCtxt = regexCtxt;
22600#ifdef DEBUG_AUTOMATA
22601 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22602 pielem->localName);
22603#endif
22604 }
22605
22606 /*
22607 * SPEC (2.4) "If the {content type} is element-only or mixed,
22608 * then the sequence of the element information item's
22609 * element information item [children], if any, taken in
22610 * order, is ·valid· with respect to the {content type}'s
22611 * particle, as defined in Element Sequence Locally Valid
22612 * (Particle) (§3.9.4)."
22613 */
22614 ret = xmlRegExecPushString2(regexCtxt,
22615 vctxt->inode->localName,
22616 vctxt->inode->nsName,
22617 vctxt->inode);
22618#ifdef DEBUG_AUTOMATA
22619 if (ret < 0)
22620 xmlGenericError(xmlGenericErrorContext,
22621 "AUTOMATON push ERROR for '%s' on '%s'\n",
22622 vctxt->inode->localName, pielem->localName);
22623 else
22624 xmlGenericError(xmlGenericErrorContext,
22625 "AUTOMATON push OK for '%s' on '%s'\n",
22626 vctxt->inode->localName, pielem->localName);
22627#endif
22628 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22629 VERROR_INT("xmlSchemaValidateChildElem",
22630 "calling xmlRegExecPushString2()");
22631 return (-1);
22632 }
22633 if (ret < 0) {
22634 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22635 &values[0], &terminal);
22636 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22637 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22638 "This element is not expected",
22639 nbval, nbneg, values);
22640 ret = vctxt->err;
22641 goto unexpected_elem;
22642 } else
22643 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022644 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022645 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022646 case XML_SCHEMA_CONTENT_SIMPLE:
22647 case XML_SCHEMA_CONTENT_BASIC:
22648 ACTIVATE_PARENT_ELEM
22649 if (IS_COMPLEX_TYPE(ptype)) {
22650 /*
22651 * SPEC (cvc-complex-type) (2.2)
22652 * "If the {content type} is a simple type definition, then
22653 * the element information item has no element information
22654 * item [children], ..."
22655 */
22656 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22657 VERROR(ret, NULL, "Element content is not allowed, "
22658 "because the content type is a simple type definition");
22659 } else {
22660 /*
22661 * SPEC (cvc-type) (3.1.2) "The element information item must
22662 * have no element information item [children]."
22663 */
22664 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22665 VERROR(ret, NULL, "Element content is not allowed, "
22666 "because the type definition is simple");
22667 }
22668 ACTIVATE_ELEM
22669 ret = vctxt->err;
22670 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022671 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022672
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022673 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022674 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022675 }
22676 return (ret);
22677unexpected_elem:
22678 /*
22679 * Pop this element and set the skipDepth to skip
22680 * all further content of the parent element.
22681 */
22682 vctxt->skipDepth = vctxt->depth;
22683 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22684 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22685 return (ret);
22686}
22687
22688#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22689#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22690#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22691
22692static int
22693xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22694 int nodeType, const xmlChar *value, int len,
22695 int mode, int *consumed)
22696{
22697 /*
22698 * Unfortunately we have to duplicate the text sometimes.
22699 * OPTIMIZE: Maybe we could skip it, if:
22700 * 1. content type is simple
22701 * 2. whitespace is "collapse"
22702 * 3. it consists of whitespace only
22703 *
22704 * Process character content.
22705 */
22706 if (consumed != NULL)
22707 *consumed = 0;
22708 if (INODE_NILLED(vctxt->inode)) {
22709 /*
22710 * SPEC cvc-elt (3.3.4 - 3.2.1)
22711 * "The element information item must have no character or
22712 * element information item [children]."
22713 */
22714 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22715 "Neither character nor element content is allowed "
22716 "because the element is 'nilled'");
22717 return (vctxt->err);
22718 }
22719 /*
22720 * SPEC (2.1) "If the {content type} is empty, then the
22721 * element information item has no character or element
22722 * information item [children]."
22723 */
22724 if (vctxt->inode->typeDef->contentType ==
22725 XML_SCHEMA_CONTENT_EMPTY) {
22726 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22727 "Character content is not allowed, "
22728 "because the content type is empty");
22729 return (vctxt->err);
22730 }
22731
22732 if (vctxt->inode->typeDef->contentType ==
22733 XML_SCHEMA_CONTENT_ELEMENTS) {
22734 if ((nodeType != XML_TEXT_NODE) ||
22735 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22736 /*
22737 * SPEC cvc-complex-type (2.3)
22738 * "If the {content type} is element-only, then the
22739 * element information item has no character information
22740 * item [children] other than those whose [character
22741 * code] is defined as a white space in [XML 1.0 (Second
22742 * Edition)]."
22743 */
22744 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22745 "Character content other than whitespace is not allowed "
22746 "because the content type is 'element-only'");
22747 return (vctxt->err);
22748 }
22749 return (0);
22750 }
22751
22752 if ((value == NULL) || (value[0] == 0))
22753 return (0);
22754 /*
22755 * Save the value.
22756 * NOTE that even if the content type is *mixed*, we need the
22757 * *initial value* for default/fixed value constraints.
22758 */
22759 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22760 ((vctxt->inode->decl == NULL) ||
22761 (vctxt->inode->decl->value == NULL)))
22762 return (0);
22763
22764 if (vctxt->inode->value == NULL) {
22765 /*
22766 * Set the value.
22767 */
22768 switch (mode) {
22769 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22770 /*
22771 * When working on a tree.
22772 */
22773 vctxt->inode->value = value;
22774 break;
22775 case XML_SCHEMA_PUSH_TEXT_CREATED:
22776 /*
22777 * When working with the reader.
22778 * The value will be freed by the element info.
22779 */
22780 vctxt->inode->value = value;
22781 if (consumed != NULL)
22782 *consumed = 1;
22783 vctxt->inode->flags |=
22784 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22785 break;
22786 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22787 /*
22788 * When working with SAX.
22789 * The value will be freed by the element info.
22790 */
22791 if (len != -1)
22792 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22793 else
22794 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22795 vctxt->inode->flags |=
22796 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22797 break;
22798 default:
22799 break;
22800 }
22801 } else {
22802 /*
22803 * Concat the value.
22804 */
22805 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022806 vctxt->inode->value = BAD_CAST xmlStrncat(
22807 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022808 } else {
22809 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022810 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022811 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22812 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022813 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022814
22815 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022816}
22817
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022818static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022819xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022820{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022821 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022822
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022823 if ((vctxt->skipDepth != -1) &&
22824 (vctxt->depth >= vctxt->skipDepth)) {
22825 VERROR_INT("xmlSchemaValidateElem",
22826 "in skip-state");
22827 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022828 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022829 if (vctxt->xsiAssemble) {
22830 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22831 goto internal_error;
22832 }
22833 if (vctxt->depth > 0) {
22834 /*
22835 * Validate this element against the content model
22836 * of the parent.
22837 */
22838 ret = xmlSchemaValidateChildElem(vctxt);
22839 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022840 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022841 VERROR_INT("xmlSchemaValidateElem",
22842 "calling xmlSchemaStreamValidateChildElement()");
22843 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022844 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022845 goto exit;
22846 }
22847 if (vctxt->depth == vctxt->skipDepth)
22848 goto exit;
22849 if ((vctxt->inode->decl == NULL) &&
22850 (vctxt->inode->typeDef == NULL)) {
22851 VERROR_INT("xmlSchemaValidateElem",
22852 "the child element was valid but neither the "
22853 "declaration nor the type was set");
22854 goto internal_error;
22855 }
22856 } else {
22857 /*
22858 * Get the declaration of the validation root.
22859 */
22860 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22861 vctxt->inode->localName,
22862 vctxt->inode->nsName);
22863 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022864 ret = XML_SCHEMAV_CVC_ELT_1;
22865 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022866 "No matching global declaration available "
22867 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022868 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022869 }
22870 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022871
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022872 if (vctxt->inode->decl == NULL)
22873 goto type_validation;
22874
22875 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22876 int skip;
22877 /*
22878 * Wildcards.
22879 */
22880 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22881 if (ret != 0) {
22882 if (ret < 0) {
22883 VERROR_INT("xmlSchemaValidateElem",
22884 "calling xmlSchemaValidateElemWildcard()");
22885 goto internal_error;
22886 }
22887 goto exit;
22888 }
22889 if (skip) {
22890 vctxt->skipDepth = vctxt->depth;
22891 goto exit;
22892 }
22893 /*
22894 * The declaration might be set by the wildcard validation,
22895 * when the processContents is "lax" or "strict".
22896 */
22897 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22898 /*
22899 * Clear the "decl" field to not confuse further processing.
22900 */
22901 vctxt->inode->decl = NULL;
22902 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022903 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022904 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022905 /*
22906 * Validate against the declaration.
22907 */
22908 ret = xmlSchemaValidateElemDecl(vctxt);
22909 if (ret != 0) {
22910 if (ret < 0) {
22911 VERROR_INT("xmlSchemaValidateElem",
22912 "calling xmlSchemaValidateElemDecl()");
22913 goto internal_error;
22914 }
22915 goto exit;
22916 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022917 /*
22918 * Validate against the type definition.
22919 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022920type_validation:
22921
22922 if (vctxt->inode->typeDef == NULL) {
22923 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22924 ret = XML_SCHEMAV_CVC_TYPE_1;
22925 VERROR(ret, NULL,
22926 "The type definition is absent");
22927 goto exit;
22928 }
22929 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22930 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22931 ret = XML_SCHEMAV_CVC_TYPE_2;
22932 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022933 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022934 goto exit;
22935 }
22936 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022937 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022938 * during validation against the declaration. This must be done
22939 * _before_ attribute validation.
22940 */
22941 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22942 if (ret == -1) {
22943 VERROR_INT("xmlSchemaValidateElem",
22944 "calling xmlSchemaXPathEvaluate()");
22945 goto internal_error;
22946 }
22947 /*
22948 * Validate attributes.
22949 */
22950 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22951 if ((vctxt->nbAttrInfos != 0) ||
22952 (vctxt->inode->typeDef->attributeUses != NULL)) {
22953
22954 ret = xmlSchemaVAttributesComplex(vctxt);
22955 }
22956 } else if (vctxt->nbAttrInfos != 0) {
22957
22958 ret = xmlSchemaVAttributesSimple(vctxt);
22959 }
22960 /*
22961 * Clear registered attributes.
22962 */
22963 if (vctxt->nbAttrInfos != 0)
22964 xmlSchemaClearAttrInfos(vctxt);
22965 if (ret == -1) {
22966 VERROR_INT("xmlSchemaValidateElem",
22967 "calling attributes validation");
22968 goto internal_error;
22969 }
22970 /*
22971 * Don't return an error if attributes are invalid on purpose.
22972 */
22973 ret = 0;
22974
22975exit:
22976 if (ret != 0)
22977 vctxt->skipDepth = vctxt->depth;
22978 return (ret);
22979internal_error:
22980 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022981}
22982
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022983#ifdef XML_SCHEMA_READER_ENABLED
22984static int
22985xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022986{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022987 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
22988 int depth, nodeType, ret = 0, consumed;
22989 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022990
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022991 vctxt->depth = -1;
22992 ret = xmlTextReaderRead(vctxt->reader);
22993 /*
22994 * Move to the document element.
22995 */
22996 while (ret == 1) {
22997 nodeType = xmlTextReaderNodeType(vctxt->reader);
22998 if (nodeType == XML_ELEMENT_NODE)
22999 goto root_found;
23000 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023001 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023002 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023003
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023004root_found:
23005
23006 do {
23007 depth = xmlTextReaderDepth(vctxt->reader);
23008 nodeType = xmlTextReaderNodeType(vctxt->reader);
23009
23010 if (nodeType == XML_ELEMENT_NODE) {
23011
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023012 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023013 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23014 VERROR_INT("xmlSchemaVReaderWalk",
23015 "calling xmlSchemaValidatorPushElem()");
23016 goto internal_error;
23017 }
23018 ielem = vctxt->inode;
23019 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23020 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23021 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23022 /*
23023 * Is the element empty?
23024 */
23025 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23026 if (ret == -1) {
23027 VERROR_INT("xmlSchemaVReaderWalk",
23028 "calling xmlTextReaderIsEmptyElement()");
23029 goto internal_error;
23030 }
23031 if (ret) {
23032 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23033 }
23034 /*
23035 * Register attributes.
23036 */
23037 vctxt->nbAttrInfos = 0;
23038 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23039 if (ret == -1) {
23040 VERROR_INT("xmlSchemaVReaderWalk",
23041 "calling xmlTextReaderMoveToFirstAttribute()");
23042 goto internal_error;
23043 }
23044 if (ret == 1) {
23045 do {
23046 /*
23047 * VAL TODO: How do we know that the reader works on a
23048 * node tree, to be able to pass a node here?
23049 */
23050 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23051 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23052 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23053 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23054
23055 VERROR_INT("xmlSchemaVReaderWalk",
23056 "calling xmlSchemaValidatorPushAttribute()");
23057 goto internal_error;
23058 }
23059 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23060 if (ret == -1) {
23061 VERROR_INT("xmlSchemaVReaderWalk",
23062 "calling xmlTextReaderMoveToFirstAttribute()");
23063 goto internal_error;
23064 }
23065 } while (ret == 1);
23066 /*
23067 * Back to element position.
23068 */
23069 ret = xmlTextReaderMoveToElement(vctxt->reader);
23070 if (ret == -1) {
23071 VERROR_INT("xmlSchemaVReaderWalk",
23072 "calling xmlTextReaderMoveToElement()");
23073 goto internal_error;
23074 }
23075 }
23076 /*
23077 * Validate the element.
23078 */
23079 ret= xmlSchemaValidateElem(vctxt);
23080 if (ret != 0) {
23081 if (ret == -1) {
23082 VERROR_INT("xmlSchemaVReaderWalk",
23083 "calling xmlSchemaValidateElem()");
23084 goto internal_error;
23085 }
23086 goto exit;
23087 }
23088 if (vctxt->depth == vctxt->skipDepth) {
23089 int curDepth;
23090 /*
23091 * Skip all content.
23092 */
23093 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23094 ret = xmlTextReaderRead(vctxt->reader);
23095 curDepth = xmlTextReaderDepth(vctxt->reader);
23096 while ((ret == 1) && (curDepth != depth)) {
23097 ret = xmlTextReaderRead(vctxt->reader);
23098 curDepth = xmlTextReaderDepth(vctxt->reader);
23099 }
23100 if (ret < 0) {
23101 /*
23102 * VAL TODO: A reader error occured; what to do here?
23103 */
23104 ret = 1;
23105 goto exit;
23106 }
23107 }
23108 goto leave_elem;
23109 }
23110 /*
23111 * READER VAL TODO: Is an END_ELEM really never called
23112 * if the elem is empty?
23113 */
23114 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23115 goto leave_elem;
23116 } else if (nodeType == END_ELEM) {
23117 /*
23118 * Process END of element.
23119 */
23120leave_elem:
23121 ret = xmlSchemaValidatorPopElem(vctxt);
23122 if (ret != 0) {
23123 if (ret < 0) {
23124 VERROR_INT("xmlSchemaVReaderWalk",
23125 "calling xmlSchemaValidatorPopElem()");
23126 goto internal_error;
23127 }
23128 goto exit;
23129 }
23130 if (vctxt->depth >= 0)
23131 ielem = vctxt->inode;
23132 else
23133 ielem = NULL;
23134 } else if ((nodeType == XML_TEXT_NODE) ||
23135 (nodeType == XML_CDATA_SECTION_NODE) ||
23136 (nodeType == WHTSP) ||
23137 (nodeType == SIGN_WHTSP)) {
23138 /*
23139 * Process character content.
23140 */
23141 xmlChar *value;
23142
23143 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23144 nodeType = XML_TEXT_NODE;
23145
23146 value = xmlTextReaderValue(vctxt->reader);
23147 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23148 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23149 if (! consumed)
23150 xmlFree(value);
23151 if (ret == -1) {
23152 VERROR_INT("xmlSchemaVReaderWalk",
23153 "calling xmlSchemaVPushText()");
23154 goto internal_error;
23155 }
23156 } else if ((nodeType == XML_ENTITY_NODE) ||
23157 (nodeType == XML_ENTITY_REF_NODE)) {
23158 /*
23159 * VAL TODO: What to do with entities?
23160 */
23161 TODO
23162 }
23163 /*
23164 * Read next node.
23165 */
23166 ret = xmlTextReaderRead(vctxt->reader);
23167 } while (ret == 1);
23168
23169exit:
23170 return (ret);
23171internal_error:
23172 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023173}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023174#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023175
23176/************************************************************************
23177 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023178 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023179 * *
23180 ************************************************************************/
23181
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023182#ifdef XML_SCHEMA_SAX_ENABLED
23183/*
23184* Process text content.
23185*/
23186static void
23187xmlSchemaSAXHandleText(void *ctx,
23188 const xmlChar * ch,
23189 int len)
23190{
23191 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23192
23193 if (vctxt->depth < 0)
23194 return;
23195 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23196 return;
23197 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23198 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23199 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23200 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23201 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23202 "calling xmlSchemaVPushText()");
23203 vctxt->err = -1;
23204 xmlStopParser(vctxt->parserCtxt);
23205 }
23206}
23207
23208/*
23209* Process CDATA content.
23210*/
23211static void
23212xmlSchemaSAXHandleCDataSection(void *ctx,
23213 const xmlChar * ch,
23214 int len)
23215{
23216 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23217
23218 if (vctxt->depth < 0)
23219 return;
23220 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23221 return;
23222 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23223 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23224 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23225 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23226 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23227 "calling xmlSchemaVPushText()");
23228 vctxt->err = -1;
23229 xmlStopParser(vctxt->parserCtxt);
23230 }
23231}
23232
23233static void
23234xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23235 const xmlChar * name ATTRIBUTE_UNUSED)
23236{
23237 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23238
23239 if (vctxt->depth < 0)
23240 return;
23241 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23242 return;
23243 /* SAX VAL TODO: What to do here? */
23244 TODO
23245}
23246
23247static void
23248xmlSchemaSAXHandleStartElementNs(void *ctx,
23249 const xmlChar * localname,
23250 const xmlChar * prefix ATTRIBUTE_UNUSED,
23251 const xmlChar * URI,
23252 int nb_namespaces,
23253 const xmlChar ** namespaces,
23254 int nb_attributes,
23255 int nb_defaulted ATTRIBUTE_UNUSED,
23256 const xmlChar ** attributes)
23257{
23258 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23259 int ret;
23260 xmlSchemaNodeInfoPtr ielem;
23261 int i, j;
23262
23263 /*
23264 * SAX VAL TODO: What to do with nb_defaulted?
23265 */
23266 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023267 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023268 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023269 vctxt->depth++;
23270 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023271 return;
23272 /*
23273 * Push the element.
23274 */
23275 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23276 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23277 "calling xmlSchemaValidatorPushElem()");
23278 goto internal_error;
23279 }
23280 ielem = vctxt->inode;
23281 ielem->localName = localname;
23282 ielem->nsName = URI;
23283 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23284 /*
23285 * Register namespaces on the elem info.
23286 */
23287 if (nb_namespaces != 0) {
23288 /*
23289 * Although the parser builds its own namespace list,
23290 * we have no access to it, so we'll use an own one.
23291 */
23292 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23293 /*
23294 * Store prefix and namespace name.
23295 */
23296 if (ielem->nsBindings == NULL) {
23297 ielem->nsBindings =
23298 (const xmlChar **) xmlMalloc(10 *
23299 sizeof(const xmlChar *));
23300 if (ielem->nsBindings == NULL) {
23301 xmlSchemaVErrMemory(vctxt,
23302 "allocating namespace bindings for SAX validation",
23303 NULL);
23304 goto internal_error;
23305 }
23306 ielem->nbNsBindings = 0;
23307 ielem->sizeNsBindings = 5;
23308 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23309 ielem->sizeNsBindings *= 2;
23310 ielem->nsBindings =
23311 (const xmlChar **) xmlRealloc(
23312 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023313 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023314 if (ielem->nsBindings == NULL) {
23315 xmlSchemaVErrMemory(vctxt,
23316 "re-allocating namespace bindings for SAX validation",
23317 NULL);
23318 goto internal_error;
23319 }
23320 }
23321
23322 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23323 if (namespaces[j+1][0] == 0) {
23324 /*
23325 * Handle xmlns="".
23326 */
23327 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23328 } else
23329 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23330 namespaces[j+1];
23331 ielem->nbNsBindings++;
23332 }
23333 }
23334 /*
23335 * Register attributes.
23336 * SAX VAL TODO: We are not adding namespace declaration
23337 * attributes yet.
23338 */
23339 if (nb_attributes != 0) {
23340 xmlChar *value;
23341
23342 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23343 /*
23344 * Duplicate the value.
23345 */
23346 value = xmlStrndup(attributes[j+3],
23347 attributes[j+4] - attributes[j+3]);
23348 ret = xmlSchemaValidatorPushAttribute(vctxt,
23349 NULL, attributes[j], attributes[j+2], 0,
23350 value, 1);
23351 if (ret == -1) {
23352 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23353 "calling xmlSchemaValidatorPushAttribute()");
23354 goto internal_error;
23355 }
23356 }
23357 }
23358 /*
23359 * Validate the element.
23360 */
23361 ret = xmlSchemaValidateElem(vctxt);
23362 if (ret != 0) {
23363 if (ret == -1) {
23364 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23365 "calling xmlSchemaValidateElem()");
23366 goto internal_error;
23367 }
23368 goto exit;
23369 }
23370
23371exit:
23372 return;
23373internal_error:
23374 vctxt->err = -1;
23375 xmlStopParser(vctxt->parserCtxt);
23376 return;
23377}
23378
23379static void
23380xmlSchemaSAXHandleEndElementNs(void *ctx,
23381 const xmlChar * localname ATTRIBUTE_UNUSED,
23382 const xmlChar * prefix ATTRIBUTE_UNUSED,
23383 const xmlChar * URI ATTRIBUTE_UNUSED)
23384{
23385 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23386 int res;
23387
23388 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023389 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023390 */
23391 if (vctxt->skipDepth != -1) {
23392 if (vctxt->depth > vctxt->skipDepth) {
23393 vctxt->depth--;
23394 return;
23395 } else
23396 vctxt->skipDepth = -1;
23397 }
23398 /*
23399 * SAX VAL TODO: Just a temporary check.
23400 */
23401 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23402 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23403 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23404 "elem pop mismatch");
23405 }
23406 res = xmlSchemaValidatorPopElem(vctxt);
23407 if (res != 0) {
23408 if (res < 0) {
23409 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23410 "calling xmlSchemaValidatorPopElem()");
23411 goto internal_error;
23412 }
23413 goto exit;
23414 }
23415exit:
23416 return;
23417internal_error:
23418 vctxt->err = -1;
23419 xmlStopParser(vctxt->parserCtxt);
23420 return;
23421}
23422#endif
23423
Daniel Veillard4255d502002-04-16 15:50:10 +000023424/************************************************************************
23425 * *
23426 * Validation interfaces *
23427 * *
23428 ************************************************************************/
23429
23430/**
23431 * xmlSchemaNewValidCtxt:
23432 * @schema: a precompiled XML Schemas
23433 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023434 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023435 *
23436 * Returns the validation context or NULL in case of error
23437 */
23438xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023439xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23440{
Daniel Veillard4255d502002-04-16 15:50:10 +000023441 xmlSchemaValidCtxtPtr ret;
23442
23443 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23444 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023445 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023446 return (NULL);
23447 }
23448 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023449 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23450 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023451 return (ret);
23452}
23453
23454/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023455 * xmlSchemaClearValidCtxt:
23456 * @ctxt: the schema validation context
23457 *
23458 * Free the resources associated to the schema validation context;
23459 * leaves some fields alive intended for reuse of the context.
23460 */
23461static void
23462xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23463{
23464 if (vctxt == NULL)
23465 return;
23466
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023467 vctxt->flags = 0;
Daniel Veillardf10ae122005-07-10 19:03:16 +000023468 vctxt->err = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023469 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023470 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023471#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023472 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023473#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023474 if (vctxt->value != NULL) {
23475 xmlSchemaFreeValue(vctxt->value);
23476 vctxt->value = NULL;
23477 }
23478 /*
23479 * Augmented IDC information.
23480 */
23481 if (vctxt->aidcs != NULL) {
23482 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23483 do {
23484 next = cur->next;
23485 xmlFree(cur);
23486 cur = next;
23487 } while (cur != NULL);
23488 vctxt->aidcs = NULL;
23489 }
23490 if (vctxt->idcNodes != NULL) {
23491 int i;
23492 xmlSchemaPSVIIDCNodePtr item;
23493
23494 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023495 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023496 xmlFree(item->keys);
23497 xmlFree(item);
23498 }
23499 xmlFree(vctxt->idcNodes);
23500 vctxt->idcNodes = NULL;
23501 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023502 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023503 * Note that we won't delete the XPath state pool here.
23504 */
23505 if (vctxt->xpathStates != NULL) {
23506 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23507 vctxt->xpathStates = NULL;
23508 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023509 /*
23510 * Attribute info.
23511 */
23512 if (vctxt->nbAttrInfos != 0) {
23513 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023514 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023515 /*
23516 * Element info.
23517 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023518 if (vctxt->elemInfos != NULL) {
23519 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023520 xmlSchemaNodeInfoPtr ei;
23521
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023522 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023523 ei = vctxt->elemInfos[i];
23524 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023525 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023526 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023527 }
23528 }
23529}
23530
23531/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023532 * xmlSchemaFreeValidCtxt:
23533 * @ctxt: the schema validation context
23534 *
23535 * Free the resources associated to the schema validation context
23536 */
23537void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023538xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23539{
Daniel Veillard4255d502002-04-16 15:50:10 +000023540 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023541 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023542 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023543 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023544 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023545 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023546 if (ctxt->idcNodes != NULL) {
23547 int i;
23548 xmlSchemaPSVIIDCNodePtr item;
23549
23550 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023551 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023552 xmlFree(item->keys);
23553 xmlFree(item);
23554 }
23555 xmlFree(ctxt->idcNodes);
23556 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023557 if (ctxt->idcKeys != NULL) {
23558 int i;
23559 for (i = 0; i < ctxt->nbIdcKeys; i++)
23560 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23561 xmlFree(ctxt->idcKeys);
23562 }
23563
23564 if (ctxt->xpathStates != NULL)
23565 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23566 if (ctxt->xpathStatePool != NULL)
23567 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23568
23569 /*
23570 * Augmented IDC information.
23571 */
23572 if (ctxt->aidcs != NULL) {
23573 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23574 do {
23575 next = cur->next;
23576 xmlFree(cur);
23577 cur = next;
23578 } while (cur != NULL);
23579 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023580 if (ctxt->attrInfos != NULL) {
23581 int i;
23582 xmlSchemaAttrInfoPtr attr;
23583
23584 /* Just a paranoid call to the cleanup. */
23585 if (ctxt->nbAttrInfos != 0)
23586 xmlSchemaClearAttrInfos(ctxt);
23587 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23588 attr = ctxt->attrInfos[i];
23589 xmlFree(attr);
23590 }
23591 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023592 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023593 if (ctxt->elemInfos != NULL) {
23594 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023595 xmlSchemaNodeInfoPtr ei;
23596
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023597 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023598 ei = ctxt->elemInfos[i];
23599 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023600 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023601 xmlSchemaClearElemInfo(ei);
23602 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023603 }
23604 xmlFree(ctxt->elemInfos);
23605 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023606 if (ctxt->dict != NULL)
23607 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023608 xmlFree(ctxt);
23609}
23610
23611/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000023612 * xmlSchemaIsValid:
23613 * @ctxt: the schema validation context
23614 *
23615 * Check if any error was detected during validation.
23616 *
23617 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
23618 * of internal error.
23619 */
23620int
23621xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
23622{
23623 if (ctxt == NULL)
23624 return(-1);
23625 return(ctxt->err == 0);
23626}
23627
23628/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023629 * xmlSchemaSetValidErrors:
23630 * @ctxt: a schema validation context
23631 * @err: the error function
23632 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023633 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023634 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023635 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023636 */
23637void
23638xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023639 xmlSchemaValidityErrorFunc err,
23640 xmlSchemaValidityWarningFunc warn, void *ctx)
23641{
Daniel Veillard4255d502002-04-16 15:50:10 +000023642 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023643 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023644 ctxt->error = err;
23645 ctxt->warning = warn;
23646 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023647 if (ctxt->pctxt != NULL)
23648 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023649}
23650
23651/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023652 * xmlSchemaGetValidErrors:
23653 * @ctxt: a XML-Schema validation context
23654 * @err: the error function result
23655 * @warn: the warning function result
23656 * @ctx: the functions context result
23657 *
23658 * Get the error and warning callback informations
23659 *
23660 * Returns -1 in case of error and 0 otherwise
23661 */
23662int
23663xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23664 xmlSchemaValidityErrorFunc * err,
23665 xmlSchemaValidityWarningFunc * warn, void **ctx)
23666{
23667 if (ctxt == NULL)
23668 return (-1);
23669 if (err != NULL)
23670 *err = ctxt->error;
23671 if (warn != NULL)
23672 *warn = ctxt->warning;
23673 if (ctx != NULL)
23674 *ctx = ctxt->userData;
23675 return (0);
23676}
23677
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023678
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023679/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023680 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023681 * @ctxt: a schema validation context
23682 * @options: a combination of xmlSchemaValidOption
23683 *
23684 * Sets the options to be used during the validation.
23685 *
23686 * Returns 0 in case of success, -1 in case of an
23687 * API error.
23688 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023689int
23690xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23691 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023692
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023693{
23694 int i;
23695
23696 if (ctxt == NULL)
23697 return (-1);
23698 /*
23699 * WARNING: Change the start value if adding to the
23700 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023701 * TODO: Is there an other, more easy to maintain,
23702 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023703 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023704 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023705 if (options & 1<<i)
23706 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023707 }
23708 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023709 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023710}
23711
23712/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023713 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023714 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023715 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023716 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023717 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023718 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023719 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023720int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023721xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023722
23723{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023724 if (ctxt == NULL)
23725 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023726 else
23727 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023728}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023729
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023730static int
23731xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23732{
23733 xmlAttrPtr attr;
23734 int ret = 0;
23735 xmlSchemaNodeInfoPtr ielem = NULL;
23736 xmlNodePtr node, valRoot;
23737 const xmlChar *nsName;
23738
23739 /* DOC VAL TODO: Move this to the start function. */
23740 valRoot = xmlDocGetRootElement(vctxt->doc);
23741 if (valRoot == NULL) {
23742 /* VAL TODO: Error code? */
23743 VERROR(1, NULL, "The document has no document element");
23744 return (1);
23745 }
23746 vctxt->depth = -1;
23747 vctxt->validationRoot = valRoot;
23748 node = valRoot;
23749 while (node != NULL) {
23750 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23751 goto next_sibling;
23752 if (node->type == XML_ELEMENT_NODE) {
23753
23754 /*
23755 * Init the node-info.
23756 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023757 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023758 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23759 goto internal_error;
23760 ielem = vctxt->inode;
23761 ielem->node = node;
23762 ielem->localName = node->name;
23763 if (node->ns != NULL)
23764 ielem->nsName = node->ns->href;
23765 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23766 /*
23767 * Register attributes.
23768 * DOC VAL TODO: We do not register namespace declaration
23769 * attributes yet.
23770 */
23771 vctxt->nbAttrInfos = 0;
23772 if (node->properties != NULL) {
23773 attr = node->properties;
23774 do {
23775 if (attr->ns != NULL)
23776 nsName = attr->ns->href;
23777 else
23778 nsName = NULL;
23779 ret = xmlSchemaValidatorPushAttribute(vctxt,
23780 (xmlNodePtr) attr,
23781 attr->name, nsName, 0,
23782 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23783 if (ret == -1) {
23784 VERROR_INT("xmlSchemaDocWalk",
23785 "calling xmlSchemaValidatorPushAttribute()");
23786 goto internal_error;
23787 }
23788 attr = attr->next;
23789 } while (attr);
23790 }
23791 /*
23792 * Validate the element.
23793 */
23794 ret = xmlSchemaValidateElem(vctxt);
23795 if (ret != 0) {
23796 if (ret == -1) {
23797 VERROR_INT("xmlSchemaDocWalk",
23798 "calling xmlSchemaValidateElem()");
23799 goto internal_error;
23800 }
23801 /*
23802 * Don't stop validation; just skip the content
23803 * of this element.
23804 */
23805 goto leave_node;
23806 }
23807 if ((vctxt->skipDepth != -1) &&
23808 (vctxt->depth >= vctxt->skipDepth))
23809 goto leave_node;
23810 } else if ((node->type == XML_TEXT_NODE) ||
23811 (node->type == XML_CDATA_SECTION_NODE)) {
23812 /*
23813 * Process character content.
23814 */
23815 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23816 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23817 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23818 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23819 if (ret < 0) {
23820 VERROR_INT("xmlSchemaVDocWalk",
23821 "calling xmlSchemaVPushText()");
23822 goto internal_error;
23823 }
23824 /*
23825 * DOC VAL TODO: Should we skip further validation of the
23826 * element content here?
23827 */
23828 } else if ((node->type == XML_ENTITY_NODE) ||
23829 (node->type == XML_ENTITY_REF_NODE)) {
23830 /*
23831 * DOC VAL TODO: What to do with entities?
23832 */
23833 TODO
23834 } else {
23835 goto leave_node;
23836 /*
23837 * DOC VAL TODO: XInclude nodes, etc.
23838 */
23839 }
23840 /*
23841 * Walk the doc.
23842 */
23843 if (node->children != NULL) {
23844 node = node->children;
23845 continue;
23846 }
23847leave_node:
23848 if (node->type == XML_ELEMENT_NODE) {
23849 /*
23850 * Leaving the scope of an element.
23851 */
23852 if (node != vctxt->inode->node) {
23853 VERROR_INT("xmlSchemaVDocWalk",
23854 "element position mismatch");
23855 goto internal_error;
23856 }
23857 ret = xmlSchemaValidatorPopElem(vctxt);
23858 if (ret != 0) {
23859 if (ret < 0) {
23860 VERROR_INT("xmlSchemaVDocWalk",
23861 "calling xmlSchemaValidatorPopElem()");
23862 goto internal_error;
23863 }
23864 }
23865 if (node == valRoot)
23866 goto exit;
23867 }
23868next_sibling:
23869 if (node->next != NULL)
23870 node = node->next;
23871 else {
23872 node = node->parent;
23873 goto leave_node;
23874 }
23875 }
23876
23877exit:
23878 return (ret);
23879internal_error:
23880 return (-1);
23881}
23882
23883static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000023884xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023885 /*
23886 * Some initialization.
23887 */
23888 vctxt->err = 0;
23889 vctxt->nberrors = 0;
23890 vctxt->depth = -1;
23891 vctxt->skipDepth = -1;
23892 /*
23893 * Create a schema + parser if necessary.
23894 */
23895 if (vctxt->schema == NULL) {
23896
23897 if ((vctxt->pctxt == NULL) &&
23898 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23899 return (-1);
23900
23901 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23902 if (vctxt->schema == NULL) {
23903 VERROR_INT("xmlSchemaVStartValidation",
23904 "creating a schema");
23905 return (-1);
23906 }
23907 vctxt->xsiAssemble = 1;
23908 } else
23909 vctxt->xsiAssemble = 0;
23910 /*
23911 * Augment the IDC definitions.
23912 */
23913 if (vctxt->schema->idcDef != NULL) {
23914 xmlHashScan(vctxt->schema->idcDef,
23915 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23916 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000023917 return(0);
23918}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023919
Daniel Veillardf10ae122005-07-10 19:03:16 +000023920static void
23921xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023922 if (vctxt->xsiAssemble) {
23923 if (vctxt->schema != NULL) {
23924 xmlSchemaFree(vctxt->schema);
23925 vctxt->schema = NULL;
23926 }
23927 }
23928 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000023929}
23930
23931static int
23932xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23933{
23934 int ret = 0;
23935
23936 if (xmlSchemaPreRun(vctxt) < 0)
23937 return(-1);
23938
23939 if (vctxt->doc != NULL) {
23940 /*
23941 * Tree validation.
23942 */
23943 ret = xmlSchemaVDocWalk(vctxt);
23944#ifdef LIBXML_READER_ENABLED
23945 } else if (vctxt->reader != NULL) {
23946 /*
23947 * XML Reader validation.
23948 */
23949#ifdef XML_SCHEMA_READER_ENABLED
23950 ret = xmlSchemaVReaderWalk(vctxt);
23951#endif
23952#endif
23953 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
23954 /*
23955 * SAX validation.
23956 */
23957 ret = xmlParseDocument(vctxt->parserCtxt);
23958 } else {
23959 VERROR_INT("xmlSchemaVStartValidation",
23960 "no instance to validate");
23961 ret = -1;
23962 }
23963
23964 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023965 if (ret == 0)
23966 ret = vctxt->err;
23967 return (ret);
23968}
23969
23970/**
23971 * xmlSchemaValidateOneElement:
23972 * @ctxt: a schema validation context
23973 * @elem: an element node
23974 *
23975 * Validate a branch of a tree, starting with the given @elem.
23976 *
23977 * Returns 0 if the element and its subtree is valid, a positive error
23978 * code number otherwise and -1 in case of an internal or API error.
23979 */
23980int
23981xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
23982{
23983 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
23984 return (-1);
23985
23986 if (ctxt->schema == NULL)
23987 return (-1);
23988
23989 ctxt->doc = elem->doc;
23990 ctxt->node = elem;
23991 ctxt->validationRoot = elem;
23992 return(xmlSchemaVStart(ctxt));
23993}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023994
Daniel Veillard259f0df2004-08-18 09:13:18 +000023995/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023996 * xmlSchemaValidateDoc:
23997 * @ctxt: a schema validation context
23998 * @doc: a parsed document tree
23999 *
24000 * Validate a document tree in memory.
24001 *
24002 * Returns 0 if the document is schemas valid, a positive error code
24003 * number otherwise and -1 in case of internal or API error.
24004 */
24005int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024006xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24007{
Daniel Veillard4255d502002-04-16 15:50:10 +000024008 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024009 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024010
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024011 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024012 ctxt->node = xmlDocGetRootElement(doc);
24013 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024014 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024015 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24016 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024017 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024018 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024019 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024020 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024021 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024022}
24023
Daniel Veillardcdc82732005-07-08 15:04:06 +000024024
24025/************************************************************************
24026 * *
24027 * Function and data for SAX streaming API *
24028 * *
24029 ************************************************************************/
24030typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24031typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24032
24033struct _xmlSchemaSplitSAXData {
24034 xmlSAXHandlerPtr user_sax;
24035 void *user_data;
24036 xmlSchemaValidCtxtPtr ctxt;
24037 xmlSAXHandlerPtr schemas_sax;
24038};
24039
Daniel Veillard971771e2005-07-09 17:32:57 +000024040#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24041
24042struct _xmlSchemaSAXPlug {
24043 unsigned int magic;
24044
24045 /* the original callbacks informations */
24046 xmlSAXHandlerPtr *user_sax_ptr;
24047 xmlSAXHandlerPtr user_sax;
24048 void **user_data_ptr;
24049 void *user_data;
24050
24051 /* the block plugged back and validation informations */
24052 xmlSAXHandler schemas_sax;
24053 xmlSchemaValidCtxtPtr ctxt;
24054};
24055
Daniel Veillardcdc82732005-07-08 15:04:06 +000024056/* All those functions just bounces to the user provided SAX handlers */
24057static void
24058internalSubsetSplit(void *ctx, const xmlChar *name,
24059 const xmlChar *ExternalID, const xmlChar *SystemID)
24060{
Daniel Veillard971771e2005-07-09 17:32:57 +000024061 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024062 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24063 (ctxt->user_sax->internalSubset != NULL))
24064 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24065 SystemID);
24066}
24067
24068static int
24069isStandaloneSplit(void *ctx)
24070{
Daniel Veillard971771e2005-07-09 17:32:57 +000024071 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024072 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24073 (ctxt->user_sax->isStandalone != NULL))
24074 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24075 return(0);
24076}
24077
24078static int
24079hasInternalSubsetSplit(void *ctx)
24080{
Daniel Veillard971771e2005-07-09 17:32:57 +000024081 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024082 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24083 (ctxt->user_sax->hasInternalSubset != NULL))
24084 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24085 return(0);
24086}
24087
24088static int
24089hasExternalSubsetSplit(void *ctx)
24090{
Daniel Veillard971771e2005-07-09 17:32:57 +000024091 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024092 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24093 (ctxt->user_sax->hasExternalSubset != NULL))
24094 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24095 return(0);
24096}
24097
24098static void
24099externalSubsetSplit(void *ctx, const xmlChar *name,
24100 const xmlChar *ExternalID, const xmlChar *SystemID)
24101{
Daniel Veillard971771e2005-07-09 17:32:57 +000024102 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024103 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24104 (ctxt->user_sax->internalSubset != NULL))
24105 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24106 SystemID);
24107}
24108
24109static xmlParserInputPtr
24110resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24111{
Daniel Veillard971771e2005-07-09 17:32:57 +000024112 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024113 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24114 (ctxt->user_sax->resolveEntity != NULL))
24115 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24116 systemId));
24117 return(NULL);
24118}
24119
24120static xmlEntityPtr
24121getEntitySplit(void *ctx, const xmlChar *name)
24122{
Daniel Veillard971771e2005-07-09 17:32:57 +000024123 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024124 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24125 (ctxt->user_sax->getEntity != NULL))
24126 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24127 return(NULL);
24128}
24129
24130static xmlEntityPtr
24131getParameterEntitySplit(void *ctx, const xmlChar *name)
24132{
Daniel Veillard971771e2005-07-09 17:32:57 +000024133 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024134 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24135 (ctxt->user_sax->getParameterEntity != NULL))
24136 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24137 return(NULL);
24138}
24139
24140
24141static void
24142entityDeclSplit(void *ctx, const xmlChar *name, int type,
24143 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24144{
Daniel Veillard971771e2005-07-09 17:32:57 +000024145 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024146 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24147 (ctxt->user_sax->entityDecl != NULL))
24148 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24149 systemId, content);
24150}
24151
24152static void
24153attributeDeclSplit(void *ctx, const xmlChar * elem,
24154 const xmlChar * name, int type, int def,
24155 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24156{
Daniel Veillard971771e2005-07-09 17:32:57 +000024157 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024158 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24159 (ctxt->user_sax->attributeDecl != NULL)) {
24160 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24161 def, defaultValue, tree);
24162 } else {
24163 xmlFreeEnumeration(tree);
24164 }
24165}
24166
24167static void
24168elementDeclSplit(void *ctx, const xmlChar *name, int type,
24169 xmlElementContentPtr content)
24170{
Daniel Veillard971771e2005-07-09 17:32:57 +000024171 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024172 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24173 (ctxt->user_sax->elementDecl != NULL))
24174 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24175}
24176
24177static void
24178notationDeclSplit(void *ctx, const xmlChar *name,
24179 const xmlChar *publicId, const xmlChar *systemId)
24180{
Daniel Veillard971771e2005-07-09 17:32:57 +000024181 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024182 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24183 (ctxt->user_sax->notationDecl != NULL))
24184 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24185 systemId);
24186}
24187
24188static void
24189unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24190 const xmlChar *publicId, const xmlChar *systemId,
24191 const xmlChar *notationName)
24192{
Daniel Veillard971771e2005-07-09 17:32:57 +000024193 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024194 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24195 (ctxt->user_sax->unparsedEntityDecl != NULL))
24196 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24197 systemId, notationName);
24198}
24199
24200static void
24201setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24202{
Daniel Veillard971771e2005-07-09 17:32:57 +000024203 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024204 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24205 (ctxt->user_sax->setDocumentLocator != NULL))
24206 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24207}
24208
24209static void
24210startDocumentSplit(void *ctx)
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->startDocument != NULL))
24215 ctxt->user_sax->startDocument(ctxt->user_data);
24216}
24217
24218static void
24219endDocumentSplit(void *ctx)
24220{
Daniel Veillard971771e2005-07-09 17:32:57 +000024221 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024222 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24223 (ctxt->user_sax->endDocument != NULL))
24224 ctxt->user_sax->endDocument(ctxt->user_data);
24225}
24226
24227static void
24228processingInstructionSplit(void *ctx, const xmlChar *target,
24229 const xmlChar *data)
24230{
Daniel Veillard971771e2005-07-09 17:32:57 +000024231 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024232 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24233 (ctxt->user_sax->processingInstruction != NULL))
24234 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24235}
24236
24237static void
24238commentSplit(void *ctx, const xmlChar *value)
24239{
Daniel Veillard971771e2005-07-09 17:32:57 +000024240 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024241 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24242 (ctxt->user_sax->comment != NULL))
24243 ctxt->user_sax->comment(ctxt->user_data, value);
24244}
24245
24246/*
24247 * Varargs error callbacks to the user application, harder ...
24248 */
24249
24250static void
24251warningSplit(void *ctx, const char *msg, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024252 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024253 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24254 (ctxt->user_sax->warning != NULL)) {
24255 TODO
24256 }
24257}
24258static void
24259errorSplit(void *ctx, const char *msg, ...) {
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->error != NULL)) {
24263 TODO
24264 }
24265}
24266static void
24267fatalErrorSplit(void *ctx, const char *msg, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024268 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024269 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24270 (ctxt->user_sax->fatalError != NULL)) {
24271 TODO
24272 }
24273}
24274
24275/*
24276 * Those are function where both the user handler and the schemas handler
24277 * need to be called.
24278 */
24279static void
24280charactersSplit(void *ctx, const xmlChar *ch, int len)
24281{
Daniel Veillard971771e2005-07-09 17:32:57 +000024282 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024283 if (ctxt == NULL)
24284 return;
24285 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24286 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24287 if (ctxt->ctxt != NULL)
24288 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24289}
24290
24291static void
24292ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24293{
Daniel Veillard971771e2005-07-09 17:32:57 +000024294 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024295 if (ctxt == NULL)
24296 return;
24297 if ((ctxt->user_sax != NULL) &&
24298 (ctxt->user_sax->ignorableWhitespace != NULL))
24299 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24300 if (ctxt->ctxt != NULL)
24301 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24302}
24303
24304static void
24305cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24306{
Daniel Veillard971771e2005-07-09 17:32:57 +000024307 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024308 if (ctxt == NULL)
24309 return;
24310 if ((ctxt->user_sax != NULL) &&
24311 (ctxt->user_sax->ignorableWhitespace != NULL))
24312 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24313 if (ctxt->ctxt != NULL)
24314 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24315}
24316
24317static void
24318referenceSplit(void *ctx, const xmlChar *name)
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->reference != NULL))
24323 ctxt->user_sax->reference(ctxt->user_data, name);
24324 if (ctxt->ctxt != NULL)
24325 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24326}
24327
24328static void
24329startElementNsSplit(void *ctx, const xmlChar * localname,
24330 const xmlChar * prefix, const xmlChar * URI,
24331 int nb_namespaces, const xmlChar ** namespaces,
24332 int nb_attributes, int nb_defaulted,
24333 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024334 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024335 if (ctxt == NULL)
24336 return;
24337 if ((ctxt->user_sax != NULL) &&
24338 (ctxt->user_sax->startElementNs != NULL))
24339 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24340 URI, nb_namespaces, namespaces,
24341 nb_attributes, nb_defaulted,
24342 attributes);
24343 if (ctxt->ctxt != NULL)
24344 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24345 URI, nb_namespaces, namespaces,
24346 nb_attributes, nb_defaulted,
24347 attributes);
24348}
24349
24350static void
24351endElementNsSplit(void *ctx, const xmlChar * localname,
24352 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024353 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024354 if (ctxt == NULL)
24355 return;
24356 if ((ctxt->user_sax != NULL) &&
24357 (ctxt->user_sax->endElementNs != NULL))
24358 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24359 if (ctxt->ctxt != NULL)
24360 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24361}
24362
Daniel Veillard4255d502002-04-16 15:50:10 +000024363/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024364 * xmlSchemaSAXPlug:
24365 * @ctxt: a schema validation context
24366 * @saxptr: a pointer to the original xmlSAXHandlerPtr
24367 * @dataptr: a pointer to the original SAX user data pointer
24368 *
24369 * Plug a SAX based validation layer in a SAX parsing event flow.
24370 * The original @saxptr and @dataptr data are replaced by new pointers
24371 * but the calls to the original will be maintained.
24372 *
24373 * Returns a pointer to a data structure needed to unplug the validation layer
24374 * or NULL in case of errors.
24375 */
24376xmlSchemaSAXPlugPtr
24377xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24378 xmlSAXHandlerPtr *sax, void **user_data)
24379{
24380 xmlSchemaSAXPlugPtr ret;
24381 xmlSAXHandlerPtr old_sax;
24382
24383 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24384 return(NULL);
24385
24386 /*
24387 * We only allow to plug into SAX2 event streams
24388 */
24389 old_sax = *sax;
24390 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24391 return(NULL);
24392 if ((old_sax != NULL) &&
24393 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24394 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24395 return(NULL);
24396
24397 /*
24398 * everything seems right allocate the local data needed for that layer
24399 */
24400 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24401 if (ret == NULL) {
24402 return(NULL);
24403 }
24404 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24405 ret->magic = XML_SAX_PLUG_MAGIC;
24406 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24407 ret->ctxt = ctxt;
24408 ret->user_sax_ptr = sax;
24409 ret->user_sax = old_sax;
24410 if (old_sax == NULL) {
24411 /*
24412 * go direct, no need for the split block and functions.
24413 */
24414 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24415 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24416 /*
24417 * Note that we use the same text-function for both, to prevent
24418 * the parser from testing for ignorable whitespace.
24419 */
24420 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24421 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24422
24423 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24424 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24425
24426 ret->user_data = ctxt;
24427 *user_data = ctxt;
24428 } else {
24429 /*
24430 * for each callback unused by Schemas initialize it to the Split
24431 * routine only if non NULL in the user block, this can speed up
24432 * things at the SAX level.
24433 */
24434 if (old_sax->internalSubset != NULL)
24435 ret->schemas_sax.internalSubset = internalSubsetSplit;
24436 if (old_sax->isStandalone != NULL)
24437 ret->schemas_sax.isStandalone = isStandaloneSplit;
24438 if (old_sax->hasInternalSubset != NULL)
24439 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24440 if (old_sax->hasExternalSubset != NULL)
24441 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24442 if (old_sax->resolveEntity != NULL)
24443 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24444 if (old_sax->getEntity != NULL)
24445 ret->schemas_sax.getEntity = getEntitySplit;
24446 if (old_sax->entityDecl != NULL)
24447 ret->schemas_sax.entityDecl = entityDeclSplit;
24448 if (old_sax->notationDecl != NULL)
24449 ret->schemas_sax.notationDecl = notationDeclSplit;
24450 if (old_sax->attributeDecl != NULL)
24451 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24452 if (old_sax->elementDecl != NULL)
24453 ret->schemas_sax.elementDecl = elementDeclSplit;
24454 if (old_sax->unparsedEntityDecl != NULL)
24455 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24456 if (old_sax->setDocumentLocator != NULL)
24457 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24458 if (old_sax->startDocument != NULL)
24459 ret->schemas_sax.startDocument = startDocumentSplit;
24460 if (old_sax->endDocument != NULL)
24461 ret->schemas_sax.endDocument = endDocumentSplit;
24462 if (old_sax->processingInstruction != NULL)
24463 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24464 if (old_sax->comment != NULL)
24465 ret->schemas_sax.comment = commentSplit;
24466 if (old_sax->warning != NULL)
24467 ret->schemas_sax.warning = warningSplit;
24468 if (old_sax->error != NULL)
24469 ret->schemas_sax.error = errorSplit;
24470 if (old_sax->fatalError != NULL)
24471 ret->schemas_sax.fatalError = fatalErrorSplit;
24472 if (old_sax->getParameterEntity != NULL)
24473 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24474 if (old_sax->externalSubset != NULL)
24475 ret->schemas_sax.externalSubset = externalSubsetSplit;
24476
24477 /*
24478 * the 6 schemas callback have to go to the splitter functions
24479 * Note that we use the same text-function for ignorableWhitespace
24480 * if possible, to prevent the parser from testing for ignorable
24481 * whitespace.
24482 */
24483 ret->schemas_sax.characters = charactersSplit;
24484 if ((old_sax->ignorableWhitespace != NULL) &&
24485 (old_sax->ignorableWhitespace != old_sax->characters))
24486 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24487 else
24488 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24489 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24490 ret->schemas_sax.reference = referenceSplit;
24491 ret->schemas_sax.startElementNs = startElementNsSplit;
24492 ret->schemas_sax.endElementNs = endElementNsSplit;
24493
24494 ret->user_data_ptr = user_data;
24495 ret->user_data = *user_data;
24496 *user_data = ret;
24497 }
24498
24499 /*
24500 * plug the pointers back.
24501 */
24502 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024503 ctxt->sax = *sax;
24504 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24505 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024506 return(ret);
24507}
24508
24509/**
24510 * xmlSchemaSAXUnplug:
24511 * @plug: a data structure returned by xmlSchemaSAXPlug
24512 *
24513 * Unplug a SAX based validation layer in a SAX parsing event flow.
24514 * The original pointers used in the call are restored.
24515 *
24516 * Returns 0 in case of success and -1 in case of failure.
24517 */
24518int
24519xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24520{
24521 xmlSAXHandlerPtr *sax;
24522 void **user_data;
24523
24524 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24525 return(-1);
24526 plug->magic = 0;
24527
Daniel Veillardf10ae122005-07-10 19:03:16 +000024528 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024529 /* restore the data */
24530 sax = plug->user_sax_ptr;
24531 *sax = plug->user_sax;
24532 if (plug->user_sax != NULL) {
24533 user_data = plug->user_data_ptr;
24534 *user_data = plug->user_data;
24535 }
24536
24537 /* free and return */
24538 xmlFree(plug);
24539 return(0);
24540}
24541
24542/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024543 * xmlSchemaValidateStream:
24544 * @ctxt: a schema validation context
24545 * @input: the input to use for reading the data
24546 * @enc: an optional encoding information
24547 * @sax: a SAX handler for the resulting events
24548 * @user_data: the context to provide to the SAX handler.
24549 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024550 * Validate an input based on a flow of SAX event from the parser
24551 * and forward the events to the @sax handler with the provided @user_data
24552 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024553 *
24554 * Returns 0 if the document is schemas valid, a positive error code
24555 * number otherwise and -1 in case of internal or API error.
24556 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024557int
Daniel Veillard4255d502002-04-16 15:50:10 +000024558xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024559 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24560 xmlSAXHandlerPtr sax, void *user_data)
24561{
Daniel Veillard971771e2005-07-09 17:32:57 +000024562 xmlSchemaSAXPlugPtr plug = NULL;
24563 xmlSAXHandlerPtr old_sax = NULL;
24564 xmlParserCtxtPtr pctxt = NULL;
24565 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024566 int ret;
24567
Daniel Veillard4255d502002-04-16 15:50:10 +000024568 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024569 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024570
Daniel Veillardcdc82732005-07-08 15:04:06 +000024571 /*
24572 * prepare the parser
24573 */
24574 pctxt = xmlNewParserCtxt();
24575 if (pctxt == NULL)
24576 return (-1);
24577 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000024578 pctxt->sax = sax;
24579 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024580#if 0
24581 if (options)
24582 xmlCtxtUseOptions(pctxt, options);
24583#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024584 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024585
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024586 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024587 if (inputStream == NULL) {
24588 ret = -1;
24589 goto done;
24590 }
24591 inputPush(pctxt, inputStream);
24592 ctxt->parserCtxt = pctxt;
24593 ctxt->input = input;
24594
24595 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000024596 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000024597 */
Daniel Veillard971771e2005-07-09 17:32:57 +000024598 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
24599 if (plug == NULL) {
24600 ret = -1;
24601 goto done;
24602 }
24603 ctxt->input = input;
24604 ctxt->enc = enc;
24605 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024606 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24607 ret = xmlSchemaVStart(ctxt);
24608
24609 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24610 ret = ctxt->parserCtxt->errNo;
24611 if (ret == 0)
24612 ret = 1;
24613 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024614
24615done:
Daniel Veillard971771e2005-07-09 17:32:57 +000024616 ctxt->parserCtxt = NULL;
24617 ctxt->sax = NULL;
24618 ctxt->input = NULL;
24619 if (plug != NULL) {
24620 xmlSchemaSAXUnplug(plug);
24621 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024622 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000024623 if (pctxt != NULL) {
24624 pctxt->sax = old_sax;
24625 xmlFreeParserCtxt(pctxt);
24626 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024627 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024628}
24629
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024630/**
24631 * xmlSchemaValidateFile:
24632 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024633 * @filename: the URI of the instance
24634 * @options: a future set of options, currently unused
24635 *
24636 * Do a schemas validation of the given resource, it will use the
24637 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024638 *
24639 * Returns 0 if the document is valid, a positive error code
24640 * number otherwise and -1 in case of an internal or API error.
24641 */
24642int
24643xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024644 const char * filename,
24645 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024646{
Daniel Veillard81562d22005-06-15 13:27:56 +000024647#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024648 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024649 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024650
24651 if ((ctxt == NULL) || (filename == NULL))
24652 return (-1);
24653
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024654 input = xmlParserInputBufferCreateFilename(filename,
24655 XML_CHAR_ENCODING_NONE);
24656 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024657 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024658 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24659 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024660 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024661#else
24662 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024663#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024664}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024665
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024666#define bottom_xmlschemas
24667#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024668#endif /* LIBXML_SCHEMAS_ENABLED */