blob: 70be413b68981e354a4df775d7ae68c5faceebb3 [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;
Daniel Veillard77005e62005-07-19 16:26:18 +00001882 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001883
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];
Daniel Veillard77005e62005-07-19 16:26:18 +00001901 if (cur == NULL)
1902 continue;
1903 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
1904 (cur[3] == ' ')) {
1905 is_not = 1;
1906 cur += 4;
1907 str = xmlStrcat(str, BAD_CAST "not ");
1908 } else {
1909 is_not = 0;
1910 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001911 /*
1912 * Get the local name.
1913 */
1914 localName = NULL;
1915
1916 end = cur;
1917 if (*end == '*') {
1918 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001919 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001920 } else {
1921 while ((*end != 0) && (*end != '|'))
1922 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001923 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001924 }
1925 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001926 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001927 /*
1928 * Skip "*|*" if they come with negated expressions, since
1929 * they represent the same negated wildcard.
1930 */
1931 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1932 /*
1933 * Get the namespace name.
1934 */
1935 cur = end;
1936 if (*end == '*') {
1937 nsName = xmlStrdup(BAD_CAST "{*}");
1938 } else {
1939 while (*end != 0)
1940 end++;
1941
1942 if (i >= nbval)
1943 nsName = xmlStrdup(BAD_CAST "{##other:");
1944 else
1945 nsName = xmlStrdup(BAD_CAST "{");
1946
1947 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1948 nsName = xmlStrcat(nsName, BAD_CAST "}");
1949 }
1950 str = xmlStrcat(str, BAD_CAST nsName);
1951 FREE_AND_NULL(nsName)
1952 } else {
1953 FREE_AND_NULL(localName);
1954 continue;
1955 }
1956 }
1957 str = xmlStrcat(str, BAD_CAST localName);
1958 FREE_AND_NULL(localName);
1959
1960 if (i < nbval + nbneg -1)
1961 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001962 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001963 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001964 msg = xmlStrcat(msg, BAD_CAST str);
1965 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001966 } else
1967 msg = xmlStrcat(msg, BAD_CAST "\n");
1968 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001969 xmlFree(msg);
1970}
1971
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001972static void
1973xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1974 xmlParserErrors error,
1975 xmlNodePtr node,
1976 const xmlChar *value,
1977 unsigned long length,
1978 xmlSchemaTypePtr type,
1979 xmlSchemaFacetPtr facet,
1980 const char *message,
1981 const xmlChar *str1,
1982 const xmlChar *str2)
1983{
1984 xmlChar *str = NULL, *msg = NULL;
1985 xmlSchemaTypeType facetType;
1986 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1987
1988 xmlSchemaFormatNodeForError(&msg, actxt, node);
1989 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1990 facetType = XML_SCHEMA_FACET_ENUMERATION;
1991 /*
1992 * If enumerations are validated, one must not expect the
1993 * facet to be given.
1994 */
1995 } else
1996 facetType = facet->type;
1997 msg = xmlStrcat(msg, BAD_CAST "[");
1998 msg = xmlStrcat(msg, BAD_CAST "facet '");
1999 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2000 msg = xmlStrcat(msg, BAD_CAST "'] ");
2001 if (message == NULL) {
2002 /*
2003 * Use a default message.
2004 */
2005 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2006 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2007 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2008
2009 char len[25], actLen[25];
2010
2011 /* FIXME, TODO: What is the max expected string length of the
2012 * this value?
2013 */
2014 if (nodeType == XML_ATTRIBUTE_NODE)
2015 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2016 else
2017 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2018
2019 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2020 snprintf(actLen, 24, "%lu", length);
2021
2022 if (facetType == XML_SCHEMA_FACET_LENGTH)
2023 msg = xmlStrcat(msg,
2024 BAD_CAST "this differs from the allowed length of '%s'.\n");
2025 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2026 msg = xmlStrcat(msg,
2027 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2028 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2029 msg = xmlStrcat(msg,
2030 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2031
2032 if (nodeType == XML_ATTRIBUTE_NODE)
2033 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2034 value, (const xmlChar *) actLen, (const xmlChar *) len);
2035 else
2036 xmlSchemaErr(actxt, error, node, (const char *) msg,
2037 (const xmlChar *) actLen, (const xmlChar *) len);
2038
2039 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2040 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2041 "of the set {%s}.\n");
2042 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2043 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2044 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2045 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2046 "by the pattern '%s'.\n");
2047 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2048 facet->value);
2049 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2050 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2051 "minimum value allowed ('%s').\n");
2052 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2053 facet->value);
2054 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2055 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2056 "maximum value allowed ('%s').\n");
2057 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2058 facet->value);
2059 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2060 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2061 "'%s'.\n");
2062 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2063 facet->value);
2064 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2065 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2066 "'%s'.\n");
2067 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2068 facet->value);
2069 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2070 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2071 "digits than are allowed ('%s').\n");
2072 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2073 facet->value);
2074 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2075 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2076 "digits than are allowed ('%s').\n");
2077 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2078 facet->value);
2079 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2080 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2081 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2082 } else {
2083 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2084 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2085 }
2086 } else {
2087 msg = xmlStrcat(msg, (const xmlChar *) message);
2088 msg = xmlStrcat(msg, BAD_CAST ".\n");
2089 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2090 }
2091 FREE_AND_NULL(str)
2092 xmlFree(msg);
2093}
2094
2095#define VERROR(err, type, msg) \
2096 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2097
2098#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2099
2100#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2101
2102#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2103
2104
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002105/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002106 * xmlSchemaPMissingAttrErr:
2107 * @ctxt: the schema validation context
2108 * @ownerDes: the designation of the owner
2109 * @ownerName: the name of the owner
2110 * @ownerItem: the owner as a schema object
2111 * @ownerElem: the owner as an element node
2112 * @node: the parent element node of the missing attribute node
2113 * @type: the corresponding type of the attribute node
2114 *
2115 * Reports an illegal attribute.
2116 */
2117static void
2118xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002119 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002120 xmlSchemaTypePtr ownerItem,
2121 xmlNodePtr ownerElem,
2122 const char *name,
2123 const char *message)
2124{
2125 xmlChar *des = NULL;
2126
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002127 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2128
Daniel Veillardc0826a72004-08-10 14:17:33 +00002129 if (message != NULL)
2130 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002131 else
2132 xmlSchemaPErr(ctxt, ownerElem, error,
2133 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002134 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002135 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002136}
2137
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002138
Daniel Veillardc0826a72004-08-10 14:17:33 +00002139/**
2140 * xmlSchemaPResCompAttrErr:
2141 * @ctxt: the schema validation context
2142 * @error: the error code
2143 * @ownerDes: the designation of the owner
2144 * @ownerItem: the owner as a schema object
2145 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002146 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002147 * @refName: the referenced local name
2148 * @refURI: the referenced namespace URI
2149 * @message: optional message
2150 *
2151 * Used to report QName attribute values that failed to resolve
2152 * to schema components.
2153 */
2154static void
2155xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002156 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002157 xmlSchemaTypePtr ownerItem,
2158 xmlNodePtr ownerElem,
2159 const char *name,
2160 const xmlChar *refName,
2161 const xmlChar *refURI,
2162 xmlSchemaTypeType refType,
2163 const char *refTypeStr)
2164{
2165 xmlChar *des = NULL, *strA = NULL;
2166
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002167 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002168 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002169 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2170 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002171 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002172 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2173 "%s.\n", BAD_CAST des, BAD_CAST name,
2174 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002175 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002176 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002177 FREE_AND_NULL(strA)
2178}
2179
William M. Brack2f2a6632004-08-20 23:09:47 +00002180/**
2181 * xmlSchemaPCustomAttrErr:
2182 * @ctxt: the schema parser context
2183 * @error: the error code
2184 * @ownerDes: the designation of the owner
2185 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002186 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002187 *
2188 * Reports an illegal attribute during the parse.
2189 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002190static void
2191xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002192 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002193 xmlChar **ownerDes,
2194 xmlSchemaTypePtr ownerItem,
2195 xmlAttrPtr attr,
2196 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197{
2198 xmlChar *des = NULL;
2199
2200 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002201 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002202 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002203 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002204 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002205 } else
2206 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002207 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002208 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002209 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2210 if (ownerDes == NULL)
2211 FREE_AND_NULL(des);
2212}
2213
2214/**
2215 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002216 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002217 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002218 * @ownerDes: the designation of the attribute's owner
2219 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002220 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002222 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002223 */
2224static void
2225xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002226 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002227 xmlChar **ownerDes,
2228 xmlSchemaTypePtr ownerItem,
2229 xmlAttrPtr attr)
2230{
2231 xmlChar *des = NULL, *strA = NULL;
2232
2233 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002234 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002235 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002236 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002237 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002238 } else
2239 des = *ownerDes;
2240 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2241 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2242 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002243 if (ownerDes == NULL)
2244 FREE_AND_NULL(des);
2245 FREE_AND_NULL(strA);
2246}
2247
William M. Brack2f2a6632004-08-20 23:09:47 +00002248/**
2249 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002250 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002251 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002252 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002253 * @itemElem: the node of the schema item
2254 *
2255 * Creates a designation for an item.
2256 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002257static void
2258xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002259 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002260 xmlSchemaTypePtr item,
2261 xmlNodePtr itemElem)
2262{
2263 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002264 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002265 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002266 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002267 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002268 } else
2269 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002270}
2271
William M. Brack2f2a6632004-08-20 23:09:47 +00002272/**
2273 * xmlSchemaPCustomErr:
2274 * @ctxt: the schema parser context
2275 * @error: the error code
2276 * @itemDes: the designation of the schema item
2277 * @item: the schema item
2278 * @itemElem: the node of the schema item
2279 * @message: the error message
2280 * @str1: an optional param for the error message
2281 * @str2: an optional param for the error message
2282 * @str3: an optional param for the error message
2283 *
2284 * Reports an error during parsing.
2285 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002286static void
2287xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002288 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002289 xmlChar **itemDes,
2290 xmlSchemaTypePtr item,
2291 xmlNodePtr itemElem,
2292 const char *message,
2293 const xmlChar *str1,
2294 const xmlChar *str2,
2295 const xmlChar *str3)
2296{
2297 xmlChar *des = NULL, *msg = NULL;
2298
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002299 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002300 msg = xmlStrdup(BAD_CAST "%s: ");
2301 msg = xmlStrcat(msg, (const xmlChar *) message);
2302 msg = xmlStrcat(msg, BAD_CAST ".\n");
2303 if ((itemElem == NULL) && (item != NULL))
2304 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002305 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002306 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2307 if (itemDes == NULL)
2308 FREE_AND_NULL(des);
2309 FREE_AND_NULL(msg);
2310}
2311
William M. Brack2f2a6632004-08-20 23:09:47 +00002312/**
2313 * xmlSchemaPCustomErr:
2314 * @ctxt: the schema parser context
2315 * @error: the error code
2316 * @itemDes: the designation of the schema item
2317 * @item: the schema item
2318 * @itemElem: the node of the schema item
2319 * @message: the error message
2320 * @str1: the optional param for the error message
2321 *
2322 * Reports an error during parsing.
2323 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002324static void
2325xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002326 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002327 xmlChar **itemDes,
2328 xmlSchemaTypePtr item,
2329 xmlNodePtr itemElem,
2330 const char *message,
2331 const xmlChar *str1)
2332{
2333 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2334 str1, NULL, NULL);
2335}
2336
William M. Brack2f2a6632004-08-20 23:09:47 +00002337/**
2338 * xmlSchemaPAttrUseErr:
2339 * @ctxt: the schema parser context
2340 * @error: the error code
2341 * @itemDes: the designation of the schema type
2342 * @item: the schema type
2343 * @itemElem: the node of the schema type
2344 * @attr: the invalid schema attribute
2345 * @message: the error message
2346 * @str1: the optional param for the error message
2347 *
2348 * Reports an attribute use error during parsing.
2349 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002350static void
2351xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002352 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002353 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002354 const xmlSchemaAttributePtr attr,
2355 const char *message,
2356 const xmlChar *str1)
2357{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002358 xmlChar *str = NULL, *msg = NULL;
2359 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2360 msg = xmlStrcat(msg, BAD_CAST ", ");
2361 msg = xmlStrcat(msg,
2362 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2363 (xmlSchemaTypePtr) attr, NULL));
2364 FREE_AND_NULL(str);
2365 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002366 msg = xmlStrcat(msg, (const xmlChar *) message);
2367 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002368 xmlSchemaPErr(ctxt, attr->node, error,
2369 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002370 xmlFree(msg);
2371}
2372
William M. Brack2f2a6632004-08-20 23:09:47 +00002373/**
2374 * xmlSchemaPIllegalFacetAtomicErr:
2375 * @ctxt: the schema parser context
2376 * @error: the error code
2377 * @itemDes: the designation of the type
2378 * @item: the schema type
2379 * @baseItem: the base type of type
2380 * @facet: the illegal facet
2381 *
2382 * Reports an illegal facet for atomic simple types.
2383 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002384static void
2385xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002386 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002387 xmlChar **itemDes,
2388 xmlSchemaTypePtr item,
2389 xmlSchemaTypePtr baseItem,
2390 xmlSchemaFacetPtr facet)
2391{
2392 xmlChar *des = NULL, *strT = NULL;
2393
2394 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2395 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2396 "%s: The facet '%s' is not allowed on types derived from the "
2397 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002398 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002399 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002400 NULL, NULL);
2401 if (itemDes == NULL)
2402 FREE_AND_NULL(des);
2403 FREE_AND_NULL(strT);
2404}
2405
William M. Brack2f2a6632004-08-20 23:09:47 +00002406/**
2407 * xmlSchemaPIllegalFacetListUnionErr:
2408 * @ctxt: the schema parser context
2409 * @error: the error code
2410 * @itemDes: the designation of the schema item involved
2411 * @item: the schema item involved
2412 * @facet: the illegal facet
2413 *
2414 * Reports an illegal facet for <list> and <union>.
2415 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002416static void
2417xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002418 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002419 xmlChar **itemDes,
2420 xmlSchemaTypePtr item,
2421 xmlSchemaFacetPtr facet)
2422{
2423 xmlChar *des = NULL, *strT = NULL;
2424
2425 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002426 xmlSchemaPErr(ctxt, item->node, error,
2427 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002428 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002429 if (itemDes == NULL)
2430 FREE_AND_NULL(des);
2431 FREE_AND_NULL(strT);
2432}
2433
2434/**
2435 * xmlSchemaPMutualExclAttrErr:
2436 * @ctxt: the schema validation context
2437 * @error: the error code
2438 * @elemDes: the designation of the parent element node
2439 * @attr: the bad attribute node
2440 * @type: the corresponding type of the attribute node
2441 *
2442 * Reports an illegal attribute.
2443 */
2444static void
2445xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2446 xmlParserErrors error,
2447 xmlChar **ownerDes,
2448 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002449 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002450 const char *name1,
2451 const char *name2)
2452{
2453 xmlChar *des = NULL;
2454
2455 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002456 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002457 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002458 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002459 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002460 } else
2461 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002462 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002463 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002464 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2465 if (ownerDes == NULL)
2466 FREE_AND_NULL(des)
2467}
2468
2469/**
2470 * xmlSchemaPSimpleTypeErr:
2471 * @ctxt: the schema validation context
2472 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002473 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002474 * @ownerDes: the designation of the owner
2475 * @ownerItem: the schema object if existent
2476 * @node: the validated node
2477 * @value: the validated value
2478 *
2479 * Reports a simple type validation error.
2480 * TODO: Should this report the value of an element as well?
2481 */
2482static void
2483xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2484 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002485 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002486 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002487 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002488 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002489 const xmlChar *value,
2490 const char *message,
2491 const xmlChar *str1,
2492 const xmlChar *str2)
2493{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002494 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002495
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002496 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002497 if (message == NULL) {
2498 /*
2499 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002500 */
2501 if (type != NULL) {
2502 if (node->type == XML_ATTRIBUTE_NODE)
2503 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2504 else
2505 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2506 "valid value of ");
2507 if (! xmlSchemaIsGlobalItem(type))
2508 msg = xmlStrcat(msg, BAD_CAST "the local ");
2509 else
2510 msg = xmlStrcat(msg, BAD_CAST "the ");
2511
2512 if (VARIETY_ATOMIC(type))
2513 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2514 else if (VARIETY_LIST(type))
2515 msg = xmlStrcat(msg, BAD_CAST "list type");
2516 else if (VARIETY_UNION(type))
2517 msg = xmlStrcat(msg, BAD_CAST "union type");
2518
2519 if (xmlSchemaIsGlobalItem(type)) {
2520 xmlChar *str = NULL;
2521 msg = xmlStrcat(msg, BAD_CAST " '");
2522 if (type->builtInType != 0) {
2523 msg = xmlStrcat(msg, BAD_CAST "xs:");
2524 msg = xmlStrcat(msg, type->name);
2525 } else
2526 msg = xmlStrcat(msg,
2527 xmlSchemaFormatQName(&str,
2528 type->targetNamespace, type->name));
2529 msg = xmlStrcat(msg, BAD_CAST "'.");
2530 FREE_AND_NULL(str);
2531 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002532 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002533 if (node->type == XML_ATTRIBUTE_NODE)
2534 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2535 else
2536 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2537 "valid.");
2538 }
2539 if (expected) {
2540 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2541 msg = xmlStrcat(msg, BAD_CAST expected);
2542 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2543 } else
2544 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002545 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002546 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2547 else
2548 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2549 } else {
2550 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2551 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002552 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002553 /* Cleanup. */
2554 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002555}
2556
William M. Brack2f2a6632004-08-20 23:09:47 +00002557/**
2558 * xmlSchemaPContentErr:
2559 * @ctxt: the schema parser context
2560 * @error: the error code
2561 * @onwerDes: the designation of the holder of the content
2562 * @ownerItem: the owner item of the holder of the content
2563 * @ownerElem: the node of the holder of the content
2564 * @child: the invalid child node
2565 * @message: the optional error message
2566 * @content: the optional string describing the correct content
2567 *
2568 * Reports an error concerning the content of a schema element.
2569 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002570static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002571xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002572 xmlParserErrors error,
2573 xmlChar **ownerDes,
2574 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002575 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002576 xmlNodePtr child,
2577 const char *message,
2578 const char *content)
2579{
2580 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002581
Daniel Veillardc0826a72004-08-10 14:17:33 +00002582 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002583 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002584 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002585 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002586 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002587 } else
2588 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002589 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002590 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2591 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002592 BAD_CAST des, BAD_CAST message);
2593 else {
2594 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002595 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2596 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002597 BAD_CAST des, BAD_CAST content);
2598 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002599 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2600 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002601 BAD_CAST des, NULL);
2602 }
2603 }
2604 if (ownerDes == NULL)
2605 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002606}
2607
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002608/************************************************************************
2609 * *
2610 * Streamable error functions *
2611 * *
2612 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002613
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002614
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002615
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002616
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002617/************************************************************************
2618 * *
2619 * Validation helper functions *
2620 * *
2621 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002622
Daniel Veillardc0826a72004-08-10 14:17:33 +00002623
Daniel Veillard4255d502002-04-16 15:50:10 +00002624/************************************************************************
2625 * *
2626 * Allocation functions *
2627 * *
2628 ************************************************************************/
2629
2630/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002631 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002632 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002633 *
2634 * Allocate a new Schema structure.
2635 *
2636 * Returns the newly allocated structure or NULL in case or error
2637 */
2638static xmlSchemaPtr
2639xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2640{
2641 xmlSchemaPtr ret;
2642
2643 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2644 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002645 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002646 return (NULL);
2647 }
2648 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002649 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002650 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002651
2652 return (ret);
2653}
2654
2655/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002656 * xmlSchemaNewSchema:
2657 * @ctxt: a schema validation context
2658 *
2659 * Allocate a new Schema structure.
2660 *
2661 * Returns the newly allocated structure or NULL in case or error
2662 */
2663static xmlSchemaAssemblePtr
2664xmlSchemaNewAssemble(void)
2665{
2666 xmlSchemaAssemblePtr ret;
2667
2668 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2669 if (ret == NULL) {
2670 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2671 return (NULL);
2672 }
2673 memset(ret, 0, sizeof(xmlSchemaAssemble));
2674 ret->items = NULL;
2675 return (ret);
2676}
2677
2678/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002679 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002680 *
2681 * Allocate a new Facet structure.
2682 *
2683 * Returns the newly allocated structure or NULL in case or error
2684 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002685xmlSchemaFacetPtr
2686xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002687{
2688 xmlSchemaFacetPtr ret;
2689
2690 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2691 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002692 return (NULL);
2693 }
2694 memset(ret, 0, sizeof(xmlSchemaFacet));
2695
2696 return (ret);
2697}
2698
2699/**
2700 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002701 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002702 * @node: a node
2703 *
2704 * Allocate a new annotation structure.
2705 *
2706 * Returns the newly allocated structure or NULL in case or error
2707 */
2708static xmlSchemaAnnotPtr
2709xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2710{
2711 xmlSchemaAnnotPtr ret;
2712
2713 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2714 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002715 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002716 return (NULL);
2717 }
2718 memset(ret, 0, sizeof(xmlSchemaAnnot));
2719 ret->content = node;
2720 return (ret);
2721}
2722
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002723static xmlSchemaItemListPtr
2724xmlSchemaNewItemList(void)
2725{
2726 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002727
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002728 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2729 if (ret == NULL) {
2730 xmlSchemaPErrMemory(NULL,
2731 "allocating an item list structure", NULL);
2732 return (NULL);
2733 }
2734 memset(ret, 0, sizeof(xmlSchemaItemList));
2735 return (ret);
2736}
2737
2738/**
2739 * xmlSchemaAddElementSubstitutionMember:
2740 * @pctxt: a schema parser context
2741 * @head: the head of the substitution group
2742 * @member: the new member of the substitution group
2743 *
2744 * Allocate a new annotation structure.
2745 *
2746 * Returns the newly allocated structure or NULL in case or error
2747 */
2748static int
2749xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2750 xmlSchemaElementPtr head,
2751 xmlSchemaElementPtr member)
2752{
2753 xmlSchemaSubstGroupPtr substGroup;
2754
2755 if (pctxt == NULL)
2756 return (-1);
2757
2758 if (pctxt->substGroups == NULL) {
2759 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2760 if (pctxt->substGroups == NULL)
2761 return (-1);
2762 }
2763 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2764 head->targetNamespace);
2765 if (substGroup == NULL) {
2766 int res;
2767
2768 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2769 if (substGroup == NULL) {
2770 xmlSchemaPErrMemory(NULL,
2771 "xmlSchemaAddElementSubstitution, allocating a substitution "
2772 "group container",
2773 NULL);
2774 return (-1);
2775 }
2776 substGroup->members = xmlSchemaNewItemList();
2777 if (substGroup->members == NULL) {
2778 xmlFree(substGroup);
2779 return (-1);
2780 }
2781 substGroup->head = head;
2782
2783 res = xmlHashAddEntry2(pctxt->substGroups,
2784 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002785 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002786 xmlFree(substGroup->members);
2787 xmlFree(substGroup);
2788 xmlSchemaPErr(pctxt, member->node,
2789 XML_SCHEMAP_INTERNAL,
2790 "Internal error: xmlSchemaAddElementSubstitution, "
2791 "failed to add a new substitution group container for "
2792 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002793 return (-1);
2794 }
2795 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002796 if (substGroup->members->items == NULL) {
2797 substGroup->members->items = (void **) xmlMalloc(
2798 5 * sizeof(xmlSchemaElementPtr));
2799 if (substGroup->members->items == NULL) {
2800 xmlSchemaPErrMemory(NULL,
2801 "allocating list of substitution group members", NULL);
2802 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002803 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002804 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002805 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002806 substGroup->members->nbItems) {
2807 substGroup->members->sizeItems *= 2;
2808 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002809 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002810 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2811 if (substGroup->members->items == NULL) {
2812 xmlSchemaPErrMemory(NULL,
2813 "re-allocating list of substitution group members", NULL);
2814 substGroup->members->sizeItems = 0;
2815 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002816 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002817 }
2818 ((xmlSchemaElementPtr *) substGroup->members->items)
2819 [substGroup->members->nbItems++] = (void *) member;
2820 return (0);
2821}
2822
2823/**
2824 * xmlSchemaGetElementSubstitutionGroup:
2825 * @pctxt: a schema parser context
2826 * @head: the head of the substitution group
2827 * @member: the new member of the substitution group
2828 *
2829 * Allocate a new annotation structure.
2830 *
2831 * Returns the newly allocated structure or NULL in case or error
2832 */
2833static xmlSchemaSubstGroupPtr
2834xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2835 xmlSchemaElementPtr head)
2836{
2837 if (pctxt == NULL)
2838 return (NULL);
2839
2840 if (pctxt->substGroups == NULL)
2841 return (NULL);
2842
2843 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2844 head->name, head->targetNamespace));
2845}
2846
2847/**
2848 * xmlSchemaFreeItemList:
2849 * @annot: a schema type structure
2850 *
2851 * Deallocate a annotation structure
2852 */
2853static void
2854xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2855{
2856 if (list == NULL)
2857 return;
2858 if (list->items != NULL)
2859 xmlFree(list->items);
2860 xmlFree(list);
2861}
2862
Daniel Veillard4255d502002-04-16 15:50:10 +00002863/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002864 * xmlSchemaFreeAnnot:
2865 * @annot: a schema type structure
2866 *
2867 * Deallocate a annotation structure
2868 */
2869static void
2870xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2871{
2872 if (annot == NULL)
2873 return;
2874 xmlFree(annot);
2875}
2876
2877/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002878 * xmlSchemaFreeImport:
2879 * @import: a schema import structure
2880 *
2881 * Deallocate an import structure
2882 */
2883static void
2884xmlSchemaFreeImport(xmlSchemaImportPtr import)
2885{
2886 if (import == NULL)
2887 return;
2888
2889 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002890 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002891 xmlFree(import);
2892}
2893
2894/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002895 * xmlSchemaFreeInclude:
2896 * @include: a schema include structure
2897 *
2898 * Deallocate an include structure
2899 */
2900static void
2901xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2902{
2903 if (include == NULL)
2904 return;
2905
2906 xmlFreeDoc(include->doc);
2907 xmlFree(include);
2908}
2909
2910/**
2911 * xmlSchemaFreeIncludeList:
2912 * @includes: a schema include list
2913 *
2914 * Deallocate an include structure
2915 */
2916static void
2917xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2918{
2919 xmlSchemaIncludePtr next;
2920
2921 while (includes != NULL) {
2922 next = includes->next;
2923 xmlSchemaFreeInclude(includes);
2924 includes = next;
2925 }
2926}
2927
2928/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002929 * xmlSchemaFreeNotation:
2930 * @schema: a schema notation structure
2931 *
2932 * Deallocate a Schema Notation structure.
2933 */
2934static void
2935xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2936{
2937 if (nota == NULL)
2938 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002939 xmlFree(nota);
2940}
2941
2942/**
2943 * xmlSchemaFreeAttribute:
2944 * @schema: a schema attribute structure
2945 *
2946 * Deallocate a Schema Attribute structure.
2947 */
2948static void
2949xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2950{
2951 if (attr == NULL)
2952 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002953 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002954 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002955 if (attr->defVal != NULL)
2956 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002957 xmlFree(attr);
2958}
2959
2960/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002961 * xmlSchemaFreeWildcardNsSet:
2962 * set: a schema wildcard namespace
2963 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002964 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002965 */
2966static void
2967xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2968{
2969 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002970
Daniel Veillard3646d642004-06-02 19:19:14 +00002971 while (set != NULL) {
2972 next = set->next;
2973 xmlFree(set);
2974 set = next;
2975 }
2976}
2977
2978/**
2979 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002980 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002981 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002982 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002983 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002984void
Daniel Veillard3646d642004-06-02 19:19:14 +00002985xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2986{
2987 if (wildcard == NULL)
2988 return;
2989 if (wildcard->annot != NULL)
2990 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002991 if (wildcard->nsSet != NULL)
2992 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2993 if (wildcard->negNsSet != NULL)
2994 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002995 xmlFree(wildcard);
2996}
2997
2998/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002999 * xmlSchemaFreeAttributeGroup:
3000 * @schema: a schema attribute group structure
3001 *
3002 * Deallocate a Schema Attribute Group structure.
3003 */
3004static void
3005xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3006{
3007 if (attr == NULL)
3008 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003009 if (attr->annot != NULL)
3010 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003011 xmlFree(attr);
3012}
3013
3014/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003015 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003016 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003017 *
3018 * Deallocate a list of schema attribute uses.
3019 */
3020static void
3021xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3022{
3023 xmlSchemaAttributeLinkPtr next;
3024
3025 while (attrUse != NULL) {
3026 next = attrUse->next;
3027 xmlFree(attrUse);
3028 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003029 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003030}
3031
3032/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003033 * xmlSchemaFreeQNameRef:
3034 * @item: a QName reference structure
3035 *
3036 * Deallocatea a QName reference structure.
3037 */
3038static void
3039xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3040{
3041 xmlFree(item);
3042}
3043
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003044/**
3045 * xmlSchemaFreeQNameRef:
3046 * @item: a QName reference structure
3047 *
3048 * Deallocatea a QName reference structure.
3049 */
3050static void
3051xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3052{
3053 if (item == NULL)
3054 return;
3055 if (item->members != NULL)
3056 xmlSchemaFreeItemList(item->members);
3057 xmlFree(item);
3058}
3059
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003060static int
3061xmlSchemaAddVolatile(xmlSchemaPtr schema,
3062 xmlSchemaBasicItemPtr item)
3063{
3064 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003065
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003066 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003067 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003068 if (schema->volatiles == NULL) {
3069 xmlSchemaPErrMemory(NULL,
3070 "allocating list of volatiles", NULL);
3071 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003072 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003073 }
3074 list = (xmlSchemaItemListPtr) schema->volatiles;
3075 if (list->items == NULL) {
3076 list->items = (void **) xmlMalloc(
3077 20 * sizeof(xmlSchemaBasicItemPtr));
3078 if (list->items == NULL) {
3079 xmlSchemaPErrMemory(NULL,
3080 "allocating new volatile item buffer", NULL);
3081 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003082 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003083 list->sizeItems = 20;
3084 } else if (list->sizeItems <= list->nbItems) {
3085 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003086 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003087 list->sizeItems * sizeof(xmlSchemaTypePtr));
3088 if (list->items == NULL) {
3089 xmlSchemaPErrMemory(NULL,
3090 "growing volatile item buffer", NULL);
3091 list->sizeItems = 0;
3092 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003093 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003094 }
3095 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3096 return (0);
3097}
3098
3099/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003100 * xmlSchemaFreeTypeLinkList:
3101 * @alink: a type link
3102 *
3103 * Deallocate a list of types.
3104 */
3105static void
3106xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3107{
3108 xmlSchemaTypeLinkPtr next;
3109
3110 while (link != NULL) {
3111 next = link->next;
3112 xmlFree(link);
3113 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003114 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003115}
3116
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003117static void
3118xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3119{
3120 xmlSchemaIDCStateObjPtr next;
3121 while (sto != NULL) {
3122 next = sto->next;
3123 if (sto->history != NULL)
3124 xmlFree(sto->history);
3125 if (sto->xpathCtxt != NULL)
3126 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3127 xmlFree(sto);
3128 sto = next;
3129 }
3130}
3131
3132/**
3133 * xmlSchemaFreeIDC:
3134 * @idc: a identity-constraint definition
3135 *
3136 * Deallocates an identity-constraint definition.
3137 */
3138static void
3139xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3140{
3141 xmlSchemaIDCSelectPtr cur, prev;
3142
3143 if (idcDef == NULL)
3144 return;
3145 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003146 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003147 /* Selector */
3148 if (idcDef->selector != NULL) {
3149 if (idcDef->selector->xpathComp != NULL)
3150 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3151 xmlFree(idcDef->selector);
3152 }
3153 /* Fields */
3154 if (idcDef->fields != NULL) {
3155 cur = idcDef->fields;
3156 do {
3157 prev = cur;
3158 cur = cur->next;
3159 if (prev->xpathComp != NULL)
3160 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003161 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003162 } while (cur != NULL);
3163 }
3164 xmlFree(idcDef);
3165}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003166
Daniel Veillard01fa6152004-06-29 17:04:39 +00003167/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003168 * xmlSchemaFreeElement:
3169 * @schema: a schema element structure
3170 *
3171 * Deallocate a Schema Element structure.
3172 */
3173static void
3174xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3175{
3176 if (elem == NULL)
3177 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003178 if (elem->annot != NULL)
3179 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003180 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003181 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003182 if (elem->defVal != NULL)
3183 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003184 xmlFree(elem);
3185}
3186
3187/**
3188 * xmlSchemaFreeFacet:
3189 * @facet: a schema facet structure
3190 *
3191 * Deallocate a Schema Facet structure.
3192 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003193void
Daniel Veillard4255d502002-04-16 15:50:10 +00003194xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3195{
3196 if (facet == NULL)
3197 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003198 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003199 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003201 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003202 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003203 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003204 xmlFree(facet);
3205}
3206
3207/**
3208 * xmlSchemaFreeType:
3209 * @type: a schema type structure
3210 *
3211 * Deallocate a Schema Type structure.
3212 */
3213void
3214xmlSchemaFreeType(xmlSchemaTypePtr type)
3215{
3216 if (type == NULL)
3217 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003218 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003219 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003220 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003221 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003222
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003223 facet = type->facets;
3224 while (facet != NULL) {
3225 next = facet->next;
3226 xmlSchemaFreeFacet(facet);
3227 facet = next;
3228 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003229 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003230 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3231 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003232 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003233 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003234 if (type->memberTypes != NULL)
3235 xmlSchemaFreeTypeLinkList(type->memberTypes);
3236 if (type->facetSet != NULL) {
3237 xmlSchemaFacetLinkPtr next, link;
3238
3239 link = type->facetSet;
3240 do {
3241 next = link->next;
3242 xmlFree(link);
3243 link = next;
3244 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003245 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003246 if (type->contModel != NULL)
3247 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003248 xmlFree(type);
3249}
3250
3251/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003252 * xmlSchemaFreeModelGroupDef:
3253 * @item: a schema model group definition
3254 *
3255 * Deallocates a schema model group definition.
3256 */
3257static void
3258xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3259{
3260 if (item->annot != NULL)
3261 xmlSchemaFreeAnnot(item->annot);
3262 xmlFree(item);
3263}
3264
3265/**
3266 * xmlSchemaFreeModelGroup:
3267 * @item: a schema model group
3268 *
3269 * Deallocates a schema model group structure.
3270 */
3271static void
3272xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3273{
3274 if (item->annot != NULL)
3275 xmlSchemaFreeAnnot(item->annot);
3276 xmlFree(item);
3277}
3278
3279/**
3280 * xmlSchemaFreeParticle:
3281 * @type: a schema type structure
3282 *
3283 * Deallocate a Schema Type structure.
3284 */
3285static void
3286xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3287{
3288 if (item->annot != NULL)
3289 xmlSchemaFreeAnnot(item->annot);
3290 xmlFree(item);
3291}
3292
3293/**
3294 * xmlSchemaFreeMiscComponents:
3295 * @item: a schema component
3296 *
3297 * Deallocates misc. schema component structures.
3298 */
3299static void
3300xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3301{
3302 if (item == NULL)
3303 return;
3304 switch (item->type) {
3305 case XML_SCHEMA_TYPE_PARTICLE:
3306 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3307 return;
3308 case XML_SCHEMA_TYPE_SEQUENCE:
3309 case XML_SCHEMA_TYPE_CHOICE:
3310 case XML_SCHEMA_TYPE_ALL:
3311 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3312 return;
3313 case XML_SCHEMA_TYPE_ANY:
3314 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3315 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3316 break;
3317 default:
3318 /* TODO: This should never be hit. */
3319 TODO
3320 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003321 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003322}
3323
3324static void
3325xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3326{
3327 if (schema->volatiles == NULL)
3328 return;
3329 {
3330 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3331 xmlSchemaTreeItemPtr item;
3332 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003333
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003334 for (i = 0; i < list->nbItems; i++) {
3335 if (list->items[i] != NULL) {
3336 item = (xmlSchemaTreeItemPtr) list->items[i];
3337 switch (item->type) {
3338 case XML_SCHEMA_EXTRA_QNAMEREF:
3339 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3340 break;
3341 default:
3342 xmlSchemaFreeMiscComponents(item);
3343 }
3344 }
3345 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003346 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003347 }
3348}
3349/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003350 * xmlSchemaFreeTypeList:
3351 * @type: a schema type structure
3352 *
3353 * Deallocate a Schema Type structure.
3354 */
3355static void
3356xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3357{
3358 xmlSchemaTypePtr next;
3359
3360 while (type != NULL) {
3361 next = type->redef;
3362 xmlSchemaFreeType(type);
3363 type = next;
3364 }
3365}
3366
3367/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003368 * xmlSchemaFree:
3369 * @schema: a schema structure
3370 *
3371 * Deallocate a Schema structure.
3372 */
3373void
3374xmlSchemaFree(xmlSchemaPtr schema)
3375{
3376 if (schema == NULL)
3377 return;
3378
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003379 if (schema->volatiles != NULL)
3380 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003381 if (schema->notaDecl != NULL)
3382 xmlHashFree(schema->notaDecl,
3383 (xmlHashDeallocator) xmlSchemaFreeNotation);
3384 if (schema->attrDecl != NULL)
3385 xmlHashFree(schema->attrDecl,
3386 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3387 if (schema->attrgrpDecl != NULL)
3388 xmlHashFree(schema->attrgrpDecl,
3389 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3390 if (schema->elemDecl != NULL)
3391 xmlHashFree(schema->elemDecl,
3392 (xmlHashDeallocator) xmlSchemaFreeElement);
3393 if (schema->typeDecl != NULL)
3394 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003395 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003396 if (schema->groupDecl != NULL)
3397 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003398 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003399 if (schema->idcDef != NULL)
3400 xmlHashFree(schema->idcDef,
3401 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003402 if (schema->schemasImports != NULL)
3403 xmlHashFree(schema->schemasImports,
3404 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003405 if (schema->includes != NULL) {
3406 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3407 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003408 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003409 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003410 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003411 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003412 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003413 xmlFree(schema);
3414}
3415
3416/************************************************************************
3417 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003418 * Debug functions *
3419 * *
3420 ************************************************************************/
3421
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003422#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423
Daniel Veillard4255d502002-04-16 15:50:10 +00003424/**
3425 * xmlSchemaElementDump:
3426 * @elem: an element
3427 * @output: the file output
3428 *
3429 * Dump the element
3430 */
3431static void
3432xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003433 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003434 const xmlChar * namespace ATTRIBUTE_UNUSED,
3435 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003436{
3437 if (elem == NULL)
3438 return;
3439
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003440 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3441 fprintf(output, "Particle: %s", name);
3442 fprintf(output, ", term element: %s", elem->ref);
3443 if (elem->refNs != NULL)
3444 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003445 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003446 fprintf(output, "Element");
3447 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3448 fprintf(output, " (global)");
3449 fprintf(output, ": %s ", elem->name);
3450 if (namespace != NULL)
3451 fprintf(output, "ns %s", namespace);
3452 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003453 fprintf(output, "\n");
3454 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003455 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003456 if (elem->maxOccurs >= UNBOUNDED)
3457 fprintf(output, "max: unbounded\n");
3458 else if (elem->maxOccurs != 1)
3459 fprintf(output, "max: %d\n", elem->maxOccurs);
3460 else
3461 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003462 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003463 /*
3464 * Misc other properties.
3465 */
3466 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3467 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3468 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3469 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3470 (elem->id != NULL)) {
3471 fprintf(output, " props: ");
3472 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3473 fprintf(output, "[fixed] ");
3474 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3475 fprintf(output, "[default] ");
3476 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3477 fprintf(output, "[abstract] ");
3478 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3479 fprintf(output, "[nillable] ");
3480 if (elem->id != NULL)
3481 fprintf(output, "[id: '%s'] ", elem->id);
3482 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003483 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003484 /*
3485 * Default/fixed value.
3486 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003487 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003488 fprintf(output, " value: '%s'\n", elem->value);
3489 /*
3490 * Type.
3491 */
3492 if (elem->namedType != NULL) {
3493 fprintf(output, " type: %s ", elem->namedType);
3494 if (elem->namedTypeNs != NULL)
3495 fprintf(output, "ns %s\n", elem->namedTypeNs);
3496 else
3497 fprintf(output, "\n");
3498 }
3499 /*
3500 * Substitution group.
3501 */
3502 if (elem->substGroup != NULL) {
3503 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3504 if (elem->substGroupNs != NULL)
3505 fprintf(output, "ns %s\n", elem->substGroupNs);
3506 else
3507 fprintf(output, "\n");
3508 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003509}
3510
3511/**
3512 * xmlSchemaAnnotDump:
3513 * @output: the file output
3514 * @annot: a annotation
3515 *
3516 * Dump the annotation
3517 */
3518static void
3519xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3520{
3521 xmlChar *content;
3522
3523 if (annot == NULL)
3524 return;
3525
3526 content = xmlNodeGetContent(annot->content);
3527 if (content != NULL) {
3528 fprintf(output, " Annot: %s\n", content);
3529 xmlFree(content);
3530 } else
3531 fprintf(output, " Annot: empty\n");
3532}
3533
3534/**
3535 * xmlSchemaTypeDump:
3536 * @output: the file output
3537 * @type: a type structure
3538 *
3539 * Dump a SchemaType structure
3540 */
3541static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003542xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3543{
3544 xmlChar *str = NULL;
3545 xmlSchemaTreeItemPtr term;
3546 char shift[100];
3547 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003548
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003549 if (particle == NULL)
3550 return;
3551 for (i = 0;((i < depth) && (i < 25));i++)
3552 shift[2 * i] = shift[2 * i + 1] = ' ';
3553 shift[2 * i] = shift[2 * i + 1] = 0;
3554 fprintf(output, shift);
3555 if (particle->children == NULL) {
3556 fprintf(output, "MISSING particle term\n");
3557 return;
3558 }
3559 term = particle->children;
3560 switch (term->type) {
3561 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003562 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003563 ((xmlSchemaElementPtr)term)->targetNamespace,
3564 ((xmlSchemaElementPtr)term)->name));
3565 break;
3566 case XML_SCHEMA_TYPE_SEQUENCE:
3567 fprintf(output, "SEQUENCE");
3568 break;
3569 case XML_SCHEMA_TYPE_CHOICE:
3570 fprintf(output, "CHOICE");
3571 break;
3572 case XML_SCHEMA_TYPE_ALL:
3573 fprintf(output, "ALL");
3574 break;
3575 case XML_SCHEMA_TYPE_ANY:
3576 fprintf(output, "ANY");
3577 break;
3578 default:
3579 fprintf(output, "UNKNOWN\n");
3580 return;
3581 }
3582 if (particle->minOccurs != 1)
3583 fprintf(output, " min: %d", particle->minOccurs);
3584 if (particle->maxOccurs >= UNBOUNDED)
3585 fprintf(output, " max: unbounded");
3586 else if (particle->maxOccurs != 1)
3587 fprintf(output, " max: %d", particle->maxOccurs);
3588 fprintf(output, "\n");
3589 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3590 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3591 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3592 (term->children != NULL)) {
3593 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3594 output, depth +1);
3595 }
3596 if (particle->next != NULL)
3597 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3598 output, depth);
3599}
3600/**
3601 * xmlSchemaTypeDump:
3602 * @output: the file output
3603 * @type: a type structure
3604 *
3605 * Dump a SchemaType structure
3606 */
3607static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003608xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3609{
3610 if (type == NULL) {
3611 fprintf(output, "Type: NULL\n");
3612 return;
3613 }
3614 fprintf(output, "Type: ");
3615 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003616 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003617 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003618 fprintf(output, "no name ");
3619 if (type->targetNamespace != NULL)
3620 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 switch (type->type) {
3622 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003623 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 break;
3625 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003626 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 break;
3628 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003629 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003630 break;
3631 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003632 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003633 break;
3634 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003635 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003636 break;
3637 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003638 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003639 break;
3640 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003641 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003642 break;
3643 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003644 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003645 break;
3646 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003647 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 break;
3649 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003650 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003651 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003652 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003653 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003654 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003655 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003656 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003657 break;
3658 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003659 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003660 break;
3661 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003662 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003663 break;
3664 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003665 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003666 break;
3667 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003668 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003669 break;
3670 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003671 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003672 break;
3673 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003674 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003675 break;
3676 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003677 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 }
3680 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003681 if (type->base != NULL) {
3682 fprintf(output, " base type: %s", type->base);
3683 if (type->baseNs != NULL)
3684 fprintf(output, " ns %s\n", type->baseNs);
3685 else
3686 fprintf(output, "\n");
3687 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 if (type->annot != NULL)
3689 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003690#ifdef DUMP_CONTENT_MODEL
3691 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3692 (type->subtypes != NULL)) {
3693 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3694 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003695 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003696#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003697}
3698
3699/**
3700 * xmlSchemaDump:
3701 * @output: the file output
3702 * @schema: a schema structure
3703 *
3704 * Dump a Schema structure.
3705 */
3706void
3707xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3708{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003709 if (output == NULL)
3710 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003711 if (schema == NULL) {
3712 fprintf(output, "Schemas: NULL\n");
3713 return;
3714 }
3715 fprintf(output, "Schemas: ");
3716 if (schema->name != NULL)
3717 fprintf(output, "%s, ", schema->name);
3718 else
3719 fprintf(output, "no name, ");
3720 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003721 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003722 else
3723 fprintf(output, "no target namespace");
3724 fprintf(output, "\n");
3725 if (schema->annot != NULL)
3726 xmlSchemaAnnotDump(output, schema->annot);
3727
3728 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3729 output);
3730 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003731 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003732}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003733
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003734#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003735/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003736 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003737 * @vctxt: the WXS validation context
3738 *
3739 * Displays the current IDC table for debug purposes.
3740 */
3741static void
3742xmlSchemaDebugDumpIDCTable(FILE * output,
3743 const xmlChar *namespaceName,
3744 const xmlChar *localName,
3745 xmlSchemaPSVIIDCBindingPtr bind)
3746{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003747 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003748 xmlSchemaPSVIIDCNodePtr tab;
3749 xmlSchemaPSVIIDCKeyPtr key;
3750 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003751
3752 fprintf(output, "IDC: TABLES on %s\n",
3753 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003754 FREE_AND_NULL(str)
3755
3756 if (bind == NULL)
3757 return;
3758 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003759 fprintf(output, "IDC: BINDING %s\n",
3760 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003761 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003762 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003763 for (i = 0; i < bind->nbNodes; i++) {
3764 tab = bind->nodeTable[i];
3765 fprintf(output, " ( ");
3766 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003767 key = tab->keys[j];
3768 if ((key != NULL) && (key->val != NULL)) {
3769 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003770 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003771 fprintf(output, "\"%s\" ", value);
3772 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003773 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003774 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003775 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003776 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003777 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003778 else
3779 fprintf(output, "(key missing), ");
3780 }
3781 fprintf(output, ")\n");
3782 }
3783 bind = bind->next;
3784 } while (bind != NULL);
3785}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003786#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003787#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003788
3789/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003790 * *
3791 * Utilities *
3792 * *
3793 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003794
Daniel Veillardc0826a72004-08-10 14:17:33 +00003795/**
3796 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003797 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003798 * @name: the name of the attribute
3799 *
3800 * Seeks an attribute with a name of @name in
3801 * no namespace.
3802 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003803 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003804 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003805static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003806xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003807{
3808 xmlAttrPtr prop;
3809
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003810 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003811 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003812 prop = node->properties;
3813 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003814 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003815 return(prop);
3816 prop = prop->next;
3817 }
3818 return (NULL);
3819}
3820
3821/**
3822 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003823 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003824 * @uri: the uri
3825 * @name: the name of the attribute
3826 *
3827 * Seeks an attribute with a local name of @name and
3828 * a namespace URI of @uri.
3829 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003830 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003831 */
3832static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003833xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003834{
3835 xmlAttrPtr prop;
3836
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003837 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003838 return(NULL);
3839 prop = node->properties;
3840 while (prop != NULL) {
3841 if ((prop->ns != NULL) &&
3842 xmlStrEqual(prop->name, BAD_CAST name) &&
3843 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003844 return(prop);
3845 prop = prop->next;
3846 }
3847 return (NULL);
3848}
3849
3850static const xmlChar *
3851xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3852{
3853 xmlChar *val;
3854 const xmlChar *ret;
3855
3856 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003857 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003858 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003859 ret = xmlDictLookup(ctxt->dict, val, -1);
3860 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003861 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003862}
3863
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003864/**
3865 * xmlSchemaGetProp:
3866 * @ctxt: the parser context
3867 * @node: the node
3868 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003869 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003870 * Read a attribute value and internalize the string
3871 *
3872 * Returns the string or NULL if not present.
3873 */
3874static const xmlChar *
3875xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3876 const char *name)
3877{
3878 xmlChar *val;
3879 const xmlChar *ret;
3880
3881 val = xmlGetProp(node, BAD_CAST name);
3882 if (val == NULL)
3883 return(NULL);
3884 ret = xmlDictLookup(ctxt->dict, val, -1);
3885 xmlFree(val);
3886 return(ret);
3887}
3888
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003889/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003890 * *
3891 * Parsing functions *
3892 * *
3893 ************************************************************************/
3894
3895/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003896 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003897 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003898 * @name: the element name
3899 * @ns: the element namespace
3900 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003901 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003902 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003903 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003904 */
3905static xmlSchemaElementPtr
3906xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003907 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003908{
3909 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003910
3911 if ((name == NULL) || (schema == NULL))
3912 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003913
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003914 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003915 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003916 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003917 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003918 } else
3919 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003920 /*
3921 * This one was removed, since top level element declarations have
3922 * the target namespace specified in targetNamespace of the <schema>
3923 * information element, even if elementFormDefault is "unqualified".
3924 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003925
William M. Bracke7091952004-05-11 15:09:58 +00003926 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003927 if (xmlStrEqual(namespace, schema->targetNamespace))
3928 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3929 else
3930 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003931 if ((ret != NULL) &&
3932 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003933 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003934 }
William M. Bracke7091952004-05-11 15:09:58 +00003935 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003936
William M. Brack2f2a6632004-08-20 23:09:47 +00003937 /*
3938 * Removed since imported components will be hold by the main schema only.
3939 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003940 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003941 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003942 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003943 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003944 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003945 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003946 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3947 return (ret);
3948 } else
3949 ret = NULL;
3950 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003951 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003952#ifdef DEBUG
3953 if (ret == NULL) {
3954 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003955 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003956 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003957 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003958 namespace);
3959 }
3960#endif
3961 return (ret);
3962}
3963
3964/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003965 * xmlSchemaGetType:
3966 * @schema: the schemas context
3967 * @name: the type name
3968 * @ns: the type namespace
3969 *
3970 * Lookup a type in the schemas or the predefined types
3971 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003972 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003973 */
3974static xmlSchemaTypePtr
3975xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003976 const xmlChar * namespace)
3977{
Daniel Veillard4255d502002-04-16 15:50:10 +00003978 xmlSchemaTypePtr ret;
3979
3980 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003981 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003982 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003983 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003984 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003985 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003986 }
3987 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003988 if (ret != NULL)
3989 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003990 /*
3991 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003992 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003993 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003994 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003995 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003996 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003997 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003998 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003999 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4000 return (ret);
4001 } else
4002 ret = NULL;
4003 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004004 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004005#ifdef DEBUG
4006 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004007 if (namespace == NULL)
4008 fprintf(stderr, "Unable to lookup type %s", name);
4009 else
4010 fprintf(stderr, "Unable to lookup type %s:%s", name,
4011 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004012 }
4013#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004014 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004015}
4016
Daniel Veillard3646d642004-06-02 19:19:14 +00004017/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004018 * xmlSchemaGetAttributeDecl:
4019 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004020 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004021 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004022 *
4023 * Lookup a an attribute in the schema or imported schemas
4024 *
4025 * Returns the attribute declaration or NULL if not found.
4026 */
4027static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004028xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004029 const xmlChar * namespace)
4030{
4031 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004032
4033 if ((name == NULL) || (schema == NULL))
4034 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004035
4036
Daniel Veillard3646d642004-06-02 19:19:14 +00004037 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4038 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004039 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004040 else
4041 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004042 /*
4043 * Removed, since imported components will be hold by the main schema only.
4044 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004045 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004046 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004047 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004048 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004049 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004050 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004051 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4052 return (ret);
4053 } else
4054 ret = NULL;
4055 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004056 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004057#ifdef DEBUG
4058 if (ret == NULL) {
4059 if (namespace == NULL)
4060 fprintf(stderr, "Unable to lookup attribute %s", name);
4061 else
4062 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4063 namespace);
4064 }
4065#endif
4066 return (ret);
4067}
4068
4069/**
4070 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004071 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004072 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004073 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004074 *
4075 * Lookup a an attribute group in the schema or imported schemas
4076 *
4077 * Returns the attribute group definition or NULL if not found.
4078 */
4079static xmlSchemaAttributeGroupPtr
4080xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4081 const xmlChar * namespace)
4082{
4083 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004084
4085 if ((name == NULL) || (schema == NULL))
4086 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004087
4088
Daniel Veillard3646d642004-06-02 19:19:14 +00004089 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4090 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004091 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004092 else
4093 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004094 /*
4095 * Removed since imported components will be hold by the main schema only.
4096 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004097 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004098 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004099 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004100 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004101 if (import != NULL) {
4102 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4103 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4104 return (ret);
4105 else
4106 ret = NULL;
4107 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004108 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004109#ifdef DEBUG
4110 if (ret == NULL) {
4111 if (namespace == NULL)
4112 fprintf(stderr, "Unable to lookup attribute group %s", name);
4113 else
4114 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4115 namespace);
4116 }
4117#endif
4118 return (ret);
4119}
4120
4121/**
4122 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004123 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004124 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004125 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004126 *
4127 * Lookup a group in the schema or imported schemas
4128 *
4129 * Returns the group definition or NULL if not found.
4130 */
4131static xmlSchemaTypePtr
4132xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4133 const xmlChar * namespace)
4134{
4135 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004136
4137 if ((name == NULL) || (schema == NULL))
4138 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004139
Daniel Veillard3646d642004-06-02 19:19:14 +00004140 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004141 /*
4142 * Removed since imported components will be hold by the main schema only.
4143 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004144 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004145 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004146 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004147 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004148 if (import != NULL) {
4149 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4150 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4151 return (ret);
4152 else
4153 ret = NULL;
4154 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004155 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004156#ifdef DEBUG
4157 if (ret == NULL) {
4158 if (namespace == NULL)
4159 fprintf(stderr, "Unable to lookup group %s", name);
4160 else
4161 fprintf(stderr, "Unable to lookup group %s:%s", name,
4162 namespace);
4163 }
4164#endif
4165 return (ret);
4166}
4167
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004168/**
4169 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004170 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004171 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004172 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004173 *
4174 * Lookup a group in the schema or imported schemas
4175 *
4176 * Returns the group definition or NULL if not found.
4177 */
4178static xmlSchemaTreeItemPtr
4179xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4180 xmlSchemaTypeType itemType,
4181 const xmlChar *name,
4182 const xmlChar *targetNs)
4183{
4184 switch (itemType) {
4185 case XML_SCHEMA_TYPE_GROUP:
4186 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4187 name, targetNs));
4188 case XML_SCHEMA_TYPE_ELEMENT:
4189 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4190 name, targetNs));
4191 default:
4192 return (NULL);
4193 }
4194}
4195
Daniel Veillard4255d502002-04-16 15:50:10 +00004196/************************************************************************
4197 * *
4198 * Parsing functions *
4199 * *
4200 ************************************************************************/
4201
4202#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004203 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004204
4205/**
4206 * xmlSchemaIsBlank:
4207 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004208 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004209 *
4210 * Check if a string is ignorable
4211 *
4212 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4213 */
4214static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004215xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004216{
Daniel Veillard4255d502002-04-16 15:50:10 +00004217 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004218 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004219 if (len < 0) {
4220 while (*str != 0) {
4221 if (!(IS_BLANK_CH(*str)))
4222 return (0);
4223 str++;
4224 }
4225 } else while ((*str != 0) && (len != 0)) {
4226 if (!(IS_BLANK_CH(*str)))
4227 return (0);
4228 str++;
4229 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004230 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004231
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004232 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004233}
4234
4235/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004236 * xmlSchemaAddAssembledItem:
4237 * @ctxt: a schema parser context
4238 * @schema: the schema being built
4239 * @item: the item
4240 *
4241 * Add a item to the schema's list of current items.
4242 * This is used if the schema was already constructed and
4243 * new schemata need to be added to it.
4244 * *WARNING* this interface is highly subject to change.
4245 *
4246 * Returns 0 if suceeds and -1 if an internal error occurs.
4247 */
4248static int
4249xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4250 xmlSchemaTypePtr item)
4251{
4252 static int growSize = 100;
4253 xmlSchemaAssemblePtr ass;
4254
4255 ass = ctxt->assemble;
4256 if (ass->sizeItems < 0) {
4257 /* If disabled. */
4258 return (0);
4259 }
4260 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004261 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004262 if (ass->items == NULL) {
4263 xmlSchemaPErrMemory(ctxt,
4264 "allocating new item buffer", NULL);
4265 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004266 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004267 ass->sizeItems = growSize;
4268 } else if (ass->sizeItems <= ass->nbItems) {
4269 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004270 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004271 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4272 if (ass->items == NULL) {
4273 xmlSchemaPErrMemory(ctxt,
4274 "growing item buffer", NULL);
4275 ass->sizeItems = 0;
4276 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004277 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004278 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004279 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004280 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4281 return (0);
4282}
4283
4284/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004285 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004286 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004287 * @schema: the schema being built
4288 * @name: the item name
4289 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004290 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004291 * *WARNING* this interface is highly subject to change
4292 *
4293 * Returns the new struture or NULL in case of error
4294 */
4295static xmlSchemaNotationPtr
4296xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004297 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004298{
4299 xmlSchemaNotationPtr ret = NULL;
4300 int val;
4301
4302 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4303 return (NULL);
4304
4305 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004306 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 if (schema->notaDecl == NULL)
4308 return (NULL);
4309
4310 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4311 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004312 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004313 return (NULL);
4314 }
4315 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004316 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004317 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4318 ret);
4319 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004320 /*
4321 * TODO: This should never happen, since a unique name will be computed.
4322 * If it fails, then an other internal error must have occured.
4323 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004324 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4325 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004326 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004327 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 xmlFree(ret);
4329 return (NULL);
4330 }
4331 return (ret);
4332}
4333
4334
4335/**
4336 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004337 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004338 * @schema: the schema being built
4339 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004340 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004341 *
4342 * Add an XML schema Attrribute declaration
4343 * *WARNING* this interface is highly subject to change
4344 *
4345 * Returns the new struture or NULL in case of error
4346 */
4347static xmlSchemaAttributePtr
4348xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004349 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004350 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004351{
4352 xmlSchemaAttributePtr ret = NULL;
4353 int val;
4354
4355 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4356 return (NULL);
4357
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004358#ifdef DEBUG
4359 fprintf(stderr, "Adding attribute %s\n", name);
4360 if (namespace != NULL)
4361 fprintf(stderr, " target namespace %s\n", namespace);
4362#endif
4363
Daniel Veillard4255d502002-04-16 15:50:10 +00004364 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004365 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004366 if (schema->attrDecl == NULL)
4367 return (NULL);
4368
4369 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4370 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004371 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004372 return (NULL);
4373 }
4374 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004375 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004376 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004377 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004378 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004379 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004380 if (topLevel) {
4381 xmlSchemaPCustomErr(ctxt,
4382 XML_SCHEMAP_REDEFINED_ATTR,
4383 NULL, NULL, node,
4384 "A global attribute declaration with the name '%s' does "
4385 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004386 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004387 return (NULL);
4388 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004389 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004390 /*
4391 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4392 * in the scenario:
4393 * 1. multiple top-level complex types have different target
4394 * namespaces but have the SAME NAME; this can happen if
4395 * schemata are imported
4396 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004397 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004398 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004399 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004400 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004401 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004402 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004403
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004404 if (val != 0) {
4405 xmlSchemaPCustomErr(ctxt,
4406 XML_SCHEMAP_INTERNAL,
4407 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004408 "Internal error: xmlSchemaAddAttribute, "
4409 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004410 "could not be added to the hash.", name);
4411 xmlFree(ret);
4412 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004413 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004414 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004415 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004416 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004417 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004418 return (ret);
4419}
4420
4421/**
4422 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004423 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004424 * @schema: the schema being built
4425 * @name: the item name
4426 *
4427 * Add an XML schema Attrribute Group declaration
4428 *
4429 * Returns the new struture or NULL in case of error
4430 */
4431static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004432xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004433 xmlSchemaPtr schema, const xmlChar * name,
4434 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004435{
4436 xmlSchemaAttributeGroupPtr ret = NULL;
4437 int val;
4438
4439 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4440 return (NULL);
4441
4442 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004443 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004444 if (schema->attrgrpDecl == NULL)
4445 return (NULL);
4446
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004447 ret =
4448 (xmlSchemaAttributeGroupPtr)
4449 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004450 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004451 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004452 return (NULL);
4453 }
4454 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004455 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004456 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004457 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004459 xmlSchemaPCustomErr(ctxt,
4460 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4461 NULL, NULL, node,
4462 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004463 xmlFree(ret);
4464 return (NULL);
4465 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004466 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004467 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004468 return (ret);
4469}
4470
4471/**
4472 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004473 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004474 * @schema: the schema being built
4475 * @name: the type name
4476 * @namespace: the type namespace
4477 *
4478 * Add an XML schema Element declaration
4479 * *WARNING* this interface is highly subject to change
4480 *
4481 * Returns the new struture or NULL in case of error
4482 */
4483static xmlSchemaElementPtr
4484xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004485 const xmlChar * name, const xmlChar * namespace,
4486 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004487{
4488 xmlSchemaElementPtr ret = NULL;
4489 int val;
4490
4491 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4492 return (NULL);
4493
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004494#ifdef DEBUG
4495 fprintf(stderr, "Adding element %s\n", name);
4496 if (namespace != NULL)
4497 fprintf(stderr, " target namespace %s\n", namespace);
4498#endif
4499
Daniel Veillard4255d502002-04-16 15:50:10 +00004500 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004501 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 if (schema->elemDecl == NULL)
4503 return (NULL);
4504
4505 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4506 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004507 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004508 return (NULL);
4509 }
4510 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004511 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004512 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004513 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004514 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004515 if (topLevel) {
4516 xmlSchemaPCustomErr(ctxt,
4517 XML_SCHEMAP_REDEFINED_ELEMENT,
4518 NULL, NULL, node,
4519 "A global element declaration with the name '%s' does "
4520 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004521 xmlFree(ret);
4522 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004523 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004524 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004525
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004526 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004527 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004528 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004529 if (val != 0) {
4530 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004531 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004532 NULL, NULL, node,
4533 "Internal error: xmlSchemaAddElement, "
4534 "a dublicate element declaration with the name '%s' "
4535 "could not be added to the hash.", name);
4536 xmlFree(ret);
4537 return (NULL);
4538 }
4539 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004540
Daniel Veillard4255d502002-04-16 15:50:10 +00004541 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004542 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004543 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004544 return (ret);
4545}
4546
4547/**
4548 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004549 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004550 * @schema: the schema being built
4551 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004552 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004553 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004554 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004555 * *WARNING* this interface is highly subject to change
4556 *
4557 * Returns the new struture or NULL in case of error
4558 */
4559static xmlSchemaTypePtr
4560xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004561 const xmlChar * name, const xmlChar * namespace,
4562 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004563{
4564 xmlSchemaTypePtr ret = NULL;
4565 int val;
4566
4567 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4568 return (NULL);
4569
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004570#ifdef DEBUG
4571 fprintf(stderr, "Adding type %s\n", name);
4572 if (namespace != NULL)
4573 fprintf(stderr, " target namespace %s\n", namespace);
4574#endif
4575
Daniel Veillard4255d502002-04-16 15:50:10 +00004576 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004577 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004578 if (schema->typeDecl == NULL)
4579 return (NULL);
4580
4581 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4582 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004583 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004584 return (NULL);
4585 }
4586 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004587 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004588 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004589 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004590 if (val != 0) {
4591 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004592 xmlSchemaPCustomErr(ctxt,
4593 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004594 NULL, NULL, node,
4595 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004596 xmlFree(ret);
4597 return (NULL);
4598 } else {
4599 xmlSchemaTypePtr prev;
4600
4601 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4602 if (prev == NULL) {
4603 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004604 XML_ERR_INTERNAL_ERROR,
4605 "Internal error: xmlSchemaAddType, on type "
4606 "'%s'.\n",
4607 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004608 xmlFree(ret);
4609 return (NULL);
4610 }
4611 ret->redef = prev->redef;
4612 prev->redef = ret;
4613 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004614 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004615 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004616 ret->minOccurs = 1;
4617 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004618 ret->attributeUses = NULL;
4619 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004620 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004621 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004622 return (ret);
4623}
4624
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004625static xmlSchemaQNameRefPtr
4626xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4627 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004628 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004629 const xmlChar *refNs)
4630{
4631 xmlSchemaQNameRefPtr ret;
4632
4633 ret = (xmlSchemaQNameRefPtr)
4634 xmlMalloc(sizeof(xmlSchemaQNameRef));
4635 if (ret == NULL) {
4636 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4637 NULL);
4638 return (NULL);
4639 }
4640 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4641 ret->name = refName;
4642 ret->targetNamespace = refNs;
4643 ret->item = NULL;
4644 ret->itemType = refType;
4645 /*
4646 * Store the reference item in the schema.
4647 */
4648 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4649 return (ret);
4650}
4651
4652/**
4653 * xmlSchemaAddModelGroup:
4654 * @ctxt: a schema parser context
4655 * @schema: the schema being built
4656 * @type: the "compositor" type of the model group
4657 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004658 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004659 *
4660 * Adds a schema model group
4661 * *WARNING* this interface is highly subject to change
4662 *
4663 * Returns the new struture or NULL in case of error
4664 */
4665static xmlSchemaModelGroupPtr
4666xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4667 xmlSchemaTypeType type, const xmlChar **container,
4668 xmlNodePtr node)
4669{
4670 xmlSchemaModelGroupPtr ret = NULL;
4671 xmlChar buf[30];
4672
4673 if ((ctxt == NULL) || (schema == NULL))
4674 return (NULL);
4675
4676#ifdef DEBUG
4677 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004678#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004679 ret = (xmlSchemaModelGroupPtr)
4680 xmlMalloc(sizeof(xmlSchemaModelGroup));
4681 if (ret == NULL) {
4682 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4683 NULL);
4684 return (NULL);
4685 }
4686 ret->type = type;
4687 ret->annot = NULL;
4688 ret->node = node;
4689 ret->children = NULL;
4690 ret->next = NULL;
4691 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4692 if (container != NULL)
4693 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4694 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004695 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004696 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4697 } else {
4698 if (container != NULL)
4699 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4700 }
4701 if (container != NULL)
4702 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4703 /*
4704 * Add to volatile items.
4705 * TODO: this should be changed someday.
4706 */
4707 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4708 xmlFree(ret);
4709 return (NULL);
4710 }
4711 return (ret);
4712}
4713
4714
4715/**
4716 * xmlSchemaAddParticle:
4717 * @ctxt: a schema parser context
4718 * @schema: the schema being built
4719 * @node: the corresponding node in the schema doc
4720 * @min: the minOccurs
4721 * @max: the maxOccurs
4722 *
4723 * Adds an XML schema particle component.
4724 * *WARNING* this interface is highly subject to change
4725 *
4726 * Returns the new struture or NULL in case of error
4727 */
4728static xmlSchemaParticlePtr
4729xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4730 xmlNodePtr node, int min, int max)
4731{
4732 xmlSchemaParticlePtr ret = NULL;
4733 if ((ctxt == NULL) || (schema == NULL))
4734 return (NULL);
4735
4736#ifdef DEBUG
4737 fprintf(stderr, "Adding particle component\n");
4738#endif
4739 ret = (xmlSchemaParticlePtr)
4740 xmlMalloc(sizeof(xmlSchemaParticle));
4741 if (ret == NULL) {
4742 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4743 NULL);
4744 return (NULL);
4745 }
4746 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4747 ret->annot = NULL;
4748 ret->node = node;
4749 ret->minOccurs = min;
4750 ret->maxOccurs = max;
4751 ret->next = NULL;
4752 ret->children = NULL;
4753
4754 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4755 xmlFree(ret);
4756 return (NULL);
4757 }
4758 return (ret);
4759}
4760
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004761/**
4762 * xmlSchemaAddGroup:
4763 * @ctxt: a schema validation context
4764 * @schema: the schema being built
4765 * @name: the group name
4766 *
4767 * Add an XML schema Group definition
4768 *
4769 * Returns the new struture or NULL in case of error
4770 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004771static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004772xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004773 const xmlChar *name, const xmlChar *namespaceName,
4774 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004775{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004776 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004777 int val;
4778
4779 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4780 return (NULL);
4781
4782 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004783 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004784 if (schema->groupDecl == NULL)
4785 return (NULL);
4786
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004787 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004788 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004790 return (NULL);
4791 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004792 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004793 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004794 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004795 ret->node = node;
4796 ret->targetNamespace = namespaceName;
4797 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004798 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004799 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004800 XML_SCHEMAP_REDEFINED_GROUP,
4801 NULL, NULL, node,
4802 "A global model group definition with the name '%s' does already "
4803 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004804 xmlFree(ret);
4805 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004806 }
4807 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004808 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004809 return (ret);
4810}
4811
Daniel Veillard3646d642004-06-02 19:19:14 +00004812/**
4813 * xmlSchemaNewWildcardNs:
4814 * @ctxt: a schema validation context
4815 *
4816 * Creates a new wildcard namespace constraint.
4817 *
4818 * Returns the new struture or NULL in case of error
4819 */
4820static xmlSchemaWildcardNsPtr
4821xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4822{
4823 xmlSchemaWildcardNsPtr ret;
4824
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004825 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004826 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4827 if (ret == NULL) {
4828 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004829 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004830 }
4831 ret->value = NULL;
4832 ret->next = NULL;
4833 return (ret);
4834}
4835
4836/**
4837 * xmlSchemaAddWildcard:
4838 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004839 * @schema: a schema
4840 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004841 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004842 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004843 *
4844 * Returns the new struture or NULL in case of error
4845 */
4846static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004847xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4848 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004849{
4850 xmlSchemaWildcardPtr ret = NULL;
4851
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004852 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004853 return (NULL);
4854
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004855#ifdef DEBUG
4856 fprintf(stderr, "Adding wildcard component\n");
4857#endif
4858
Daniel Veillard3646d642004-06-02 19:19:14 +00004859 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4860 if (ret == NULL) {
4861 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4862 return (NULL);
4863 }
4864 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004865 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004866 ret->minOccurs = 1;
4867 ret->maxOccurs = 1;
4868
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004869 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4870 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4871 "Failed to add a wildcard component to the list", NULL);
4872 xmlFree(ret);
4873 return (NULL);
4874 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004875 return (ret);
4876}
4877
Daniel Veillard4255d502002-04-16 15:50:10 +00004878/************************************************************************
4879 * *
4880 * Utilities for parsing *
4881 * *
4882 ************************************************************************/
4883
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004884#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004885/**
4886 * xmlGetQNameProp:
4887 * @ctxt: a schema validation context
4888 * @node: a subtree containing XML Schema informations
4889 * @name: the attribute name
4890 * @namespace: the result namespace if any
4891 *
4892 * Extract a QName Attribute value
4893 *
4894 * Returns the NCName or NULL if not found, and also update @namespace
4895 * with the namespace URI
4896 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004897static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004898xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004899 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004900{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004901 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004902 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004903 const xmlChar *ret, *prefix;
4904 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004905 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004906
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004907 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004908 attr = xmlSchemaGetPropNode(node, name);
4909 if (attr == NULL)
4910 return (NULL);
4911 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004912
Daniel Veillard4255d502002-04-16 15:50:10 +00004913 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004914 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004915
Daniel Veillardba0153a2004-04-01 10:42:31 +00004916 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004917 ns = xmlSearchNs(node->doc, node, 0);
4918 if (ns) {
4919 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4920 return (val);
4921 }
4922 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004923 ret = xmlSplitQName3(val, &len);
4924 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004925 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004926 }
4927 ret = xmlDictLookup(ctxt->dict, ret, -1);
4928 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004929
4930 ns = xmlSearchNs(node->doc, node, prefix);
4931 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004932 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4933 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004934 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004935 "The QName value '%s' has no corresponding namespace "
4936 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004937 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004938 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004939 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004940 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004941}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004942#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004943
4944/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004945 * xmlSchemaPValAttrNodeQNameValue:
4946 * @ctxt: a schema parser context
4947 * @schema: the schema context
4948 * @ownerDes: the designation of the parent element
4949 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004950 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004951 * @local: the resulting local part if found, the attribute value otherwise
4952 * @uri: the resulting namespace URI if found
4953 *
4954 * Extracts the local name and the URI of a QName value and validates it.
4955 * This one is intended to be used on attribute values that
4956 * should resolve to schema components.
4957 *
4958 * Returns 0, in case the QName is valid, a positive error code
4959 * if not valid and -1 if an internal error occurs.
4960 */
4961static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004962xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004963 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004964 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004965 xmlSchemaTypePtr ownerItem,
4966 xmlAttrPtr attr,
4967 const xmlChar *value,
4968 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004969 const xmlChar **local)
4970{
4971 const xmlChar *pref;
4972 xmlNsPtr ns;
4973 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004974
Daniel Veillardc0826a72004-08-10 14:17:33 +00004975 *uri = NULL;
4976 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004977 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004978 if (ret > 0) {
4979 xmlSchemaPSimpleTypeErr(ctxt,
4980 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4981 ownerItem, (xmlNodePtr) attr,
4982 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4983 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004984 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004985 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004986 } else if (ret < 0)
4987 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004988
4989 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004990 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4991 if (ns)
4992 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4993 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4994 /*
4995 * This one takes care of included schemas with no
4996 * target namespace.
4997 */
4998 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004999 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005000 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005001 return (0);
5002 }
5003 /*
5004 * At this point xmlSplitQName3 has to return a local name.
5005 */
5006 *local = xmlSplitQName3(value, &len);
5007 *local = xmlDictLookup(ctxt->dict, *local, -1);
5008 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005009 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5010 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005011 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005012 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005013 ownerItem, (xmlNodePtr) attr,
5014 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5015 "The value '%s' of simple type 'xs:QName' has no "
5016 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005017 return (ctxt->err);
5018 } else {
5019 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005020 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005021 return (0);
5022}
5023
5024/**
5025 * xmlSchemaPValAttrNodeQName:
5026 * @ctxt: a schema parser context
5027 * @schema: the schema context
5028 * @ownerDes: the designation of the owner element
5029 * @ownerItem: the owner as a schema object
5030 * @attr: the attribute node
5031 * @local: the resulting local part if found, the attribute value otherwise
5032 * @uri: the resulting namespace URI if found
5033 *
5034 * Extracts and validates the QName of an attribute value.
5035 * This one is intended to be used on attribute values that
5036 * should resolve to schema components.
5037 *
5038 * Returns 0, in case the QName is valid, a positive error code
5039 * if not valid and -1 if an internal error occurs.
5040 */
5041static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005042xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005043 xmlSchemaPtr schema,
5044 xmlChar **ownerDes,
5045 xmlSchemaTypePtr ownerItem,
5046 xmlAttrPtr attr,
5047 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005048 const xmlChar **local)
5049{
5050 const xmlChar *value;
5051
5052 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005053 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5054 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005055}
5056
5057/**
5058 * xmlSchemaPValAttrQName:
5059 * @ctxt: a schema parser context
5060 * @schema: the schema context
5061 * @ownerDes: the designation of the parent element
5062 * @ownerItem: the owner as a schema object
5063 * @ownerElem: the parent node of the attribute
5064 * @name: the name of the attribute
5065 * @local: the resulting local part if found, the attribute value otherwise
5066 * @uri: the resulting namespace URI if found
5067 *
5068 * Extracts and validates the QName of an attribute value.
5069 *
5070 * Returns 0, in case the QName is valid, a positive error code
5071 * if not valid and -1 if an internal error occurs.
5072 */
5073static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005074xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5075 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005076 xmlChar **ownerDes,
5077 xmlSchemaTypePtr ownerItem,
5078 xmlNodePtr ownerElem,
5079 const char *name,
5080 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005081 const xmlChar **local)
5082{
5083 xmlAttrPtr attr;
5084
5085 attr = xmlSchemaGetPropNode(ownerElem, name);
5086 if (attr == NULL) {
5087 *local = NULL;
5088 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005089 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005090 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005091 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5092 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005093}
5094
5095/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005096 * xmlSchemaPValAttrID:
5097 * @ctxt: a schema parser context
5098 * @schema: the schema context
5099 * @ownerDes: the designation of the parent element
5100 * @ownerItem: the owner as a schema object
5101 * @ownerElem: the parent node of the attribute
5102 * @name: the name of the attribute
5103 *
5104 * Extracts and validates the ID of an attribute value.
5105 *
5106 * Returns 0, in case the ID is valid, a positive error code
5107 * if not valid and -1 if an internal error occurs.
5108 */
5109static int
5110xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005111 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005112 xmlSchemaTypePtr ownerItem,
5113 xmlNodePtr ownerElem,
5114 const xmlChar *name)
5115{
5116 int ret;
5117 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005118 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005119
5120 value = xmlGetNoNsProp(ownerElem, name);
5121 if (value == NULL)
5122 return (0);
5123
5124 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5125 if (attr == NULL)
5126 return (-1);
5127
5128 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005129 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005130 /*
5131 * NOTE: the IDness might have already be declared in the DTD
5132 */
5133 if (attr->atype != XML_ATTRIBUTE_ID) {
5134 xmlIDPtr res;
5135 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005136
5137 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005138 * TODO: Use xmlSchemaStrip here; it's not exported at this
5139 * moment.
5140 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005141 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005142 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005143 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005144 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5145 if (res == NULL) {
5146 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005147 xmlSchemaPSimpleTypeErr(ctxt,
5148 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5149 ownerItem, (xmlNodePtr) attr,
5150 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5151 NULL, NULL, "Duplicate value '%s' of simple "
5152 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005153 } else
5154 attr->atype = XML_ATTRIBUTE_ID;
5155 if (strip != NULL)
5156 xmlFree(strip);
5157 }
5158 } else if (ret > 0) {
5159 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005160 xmlSchemaPSimpleTypeErr(ctxt,
5161 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5162 ownerItem, (xmlNodePtr) attr,
5163 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5164 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5165 "not a valid 'xs:NCName'",
5166 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005167 }
5168 xmlFree(value);
5169
5170 return (ret);
5171}
5172
5173/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005174 * xmlGetMaxOccurs:
5175 * @ctxt: a schema validation context
5176 * @node: a subtree containing XML Schema informations
5177 *
5178 * Get the maxOccurs property
5179 *
5180 * Returns the default if not found, or the value
5181 */
5182static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005183xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5184 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005185{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005186 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005187 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005188 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005189
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005190 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5191 if (attr == NULL)
5192 return (def);
5193 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005194
5195 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005196 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005197 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005198 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5199 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005200 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005201 val, NULL, NULL, NULL);
5202 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005203 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005204 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005205 }
5206
5207 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005208 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005209 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005210 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005211 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005212 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5213 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005214 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005215 val, NULL, NULL, NULL);
5216 return (def);
5217 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005218 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005219 ret = ret * 10 + (*cur - '0');
5220 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005221 }
William M. Brack76e95df2003-10-18 16:20:14 +00005222 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005223 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005224 /*
5225 * TODO: Restrict the maximal value to Integer.
5226 */
5227 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005228 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005229 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5230 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005231 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005232 val, NULL, NULL, NULL);
5233 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005234 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005235 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005236}
5237
5238/**
5239 * xmlGetMinOccurs:
5240 * @ctxt: a schema validation context
5241 * @node: a subtree containing XML Schema informations
5242 *
5243 * Get the minOccurs property
5244 *
5245 * Returns the default if not found, or the value
5246 */
5247static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005248xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005249 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005250{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005251 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005252 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005253 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005254
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005255 attr = xmlSchemaGetPropNode(node, "minOccurs");
5256 if (attr == NULL)
5257 return (def);
5258 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005259 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005260 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005262 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005263 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005264 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5265 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005266 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005267 val, NULL, NULL, NULL);
5268 return (def);
5269 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005270 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005271 ret = ret * 10 + (*cur - '0');
5272 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005273 }
William M. Brack76e95df2003-10-18 16:20:14 +00005274 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005275 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005276 /*
5277 * TODO: Restrict the maximal value to Integer.
5278 */
5279 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005280 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005281 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5282 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005283 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005284 val, NULL, NULL, NULL);
5285 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005286 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005287 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005288}
5289
5290/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005291 * xmlSchemaPGetBoolNodeValue:
5292 * @ctxt: a schema validation context
5293 * @ownerDes: owner designation
5294 * @ownerItem: the owner as a schema item
5295 * @node: the node holding the value
5296 *
5297 * Converts a boolean string value into 1 or 0.
5298 *
5299 * Returns 0 or 1.
5300 */
5301static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005302xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5303 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005304 xmlSchemaTypePtr ownerItem,
5305 xmlNodePtr node)
5306{
5307 xmlChar *value = NULL;
5308 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005309
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005310 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005311 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005312 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005313 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005314 * can have the following legal literals {true, false, 1, 0}.
5315 */
5316 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5317 res = 1;
5318 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5319 res = 0;
5320 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5321 res = 1;
5322 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005323 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005324 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005325 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005326 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005327 ownerItem, node,
5328 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5329 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005330 NULL, NULL, NULL);
5331 }
5332 if (value != NULL)
5333 xmlFree(value);
5334 return (res);
5335}
5336
5337/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 * xmlGetBooleanProp:
5339 * @ctxt: a schema validation context
5340 * @node: a subtree containing XML Schema informations
5341 * @name: the attribute name
5342 * @def: the default value
5343 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005344 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005345 *
5346 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005347 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005348 */
5349static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005350xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5351 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 xmlSchemaTypePtr ownerItem,
5353 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005354 const char *name, int def)
5355{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005356 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005357
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005358 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005359 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005360 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005361 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005362 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005363 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005364 * can have the following legal literals {true, false, 1, 0}.
5365 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005366 if (xmlStrEqual(val, BAD_CAST "true"))
5367 def = 1;
5368 else if (xmlStrEqual(val, BAD_CAST "false"))
5369 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005370 else if (xmlStrEqual(val, BAD_CAST "1"))
5371 def = 1;
5372 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005373 def = 0;
5374 else {
5375 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005376 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005377 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005378 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005379 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5380 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005381 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005382 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005383}
5384
5385/************************************************************************
5386 * *
5387 * Shema extraction from an Infoset *
5388 * *
5389 ************************************************************************/
5390static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5391 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005392 xmlNodePtr node,
5393 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005394static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5395 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005396 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005397 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005398 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005399static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5400 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005401 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005402 xmlNodePtr node,
5403 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005404static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5405 ctxt,
5406 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005407 xmlNodePtr node,
5408 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005409static xmlSchemaAttributeGroupPtr
5410xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005411 xmlSchemaPtr schema, xmlNodePtr node,
5412 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005413static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5414 xmlSchemaPtr schema,
5415 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005416static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005417xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5418 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005419
5420/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005421 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005422 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005423 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005424 * @ownerDes: the designation of the parent element
5425 * @ownerItem: the schema object owner if existent
5426 * @attr: the schema attribute node being validated
5427 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005428 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005429 *
5430 * Validates a value against the given built-in type.
5431 * This one is intended to be used internally for validation
5432 * of schema attribute values during parsing of the schema.
5433 *
5434 * Returns 0 if the value is valid, a positive error code
5435 * number otherwise and -1 in case of an internal or API error.
5436 */
5437static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005438xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5439 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5440 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005441 xmlAttrPtr attr,
5442 const xmlChar *value,
5443 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005444{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005445
5446 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005447
5448 /*
5449 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5450 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005451 */
5452 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005453 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005454 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5455 PERROR_INT("xmlSchemaPValAttrNodeValue",
5456 "the given type is not a built-in type");
5457 return (-1);
5458 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005459 switch (type->builtInType) {
5460 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005461 case XML_SCHEMAS_QNAME:
5462 case XML_SCHEMAS_ANYURI:
5463 case XML_SCHEMAS_TOKEN:
5464 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005465 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5466 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005467 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005468 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005469 PERROR_INT("xmlSchemaPValAttrNodeValue",
5470 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005471 return (-1);
5472 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005473 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005474 /*
5475 * TODO: Should we use the S4S error codes instead?
5476 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005477 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005478 PERROR_INT("xmlSchemaPValAttrNodeValue",
5479 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005480 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005481 } else if (ret > 0) {
5482 if (VARIETY_LIST(type))
5483 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5484 else
5485 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5486 xmlSchemaPSimpleTypeErr(pctxt,
5487 ret, ownerItem, (xmlNodePtr) attr,
5488 type, NULL, value, NULL, NULL, NULL);
5489 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005490 return (ret);
5491}
5492
5493/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005494 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005495 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005496 * @ctxt: a schema parser context
5497 * @ownerDes: the designation of the parent element
5498 * @ownerItem: the schema object owner if existent
5499 * @attr: the schema attribute node being validated
5500 * @type: the built-in type to be validated against
5501 * @value: the resulting value if any
5502 *
5503 * Extracts and validates a value against the given built-in type.
5504 * This one is intended to be used internally for validation
5505 * of schema attribute values during parsing of the schema.
5506 *
5507 * Returns 0 if the value is valid, a positive error code
5508 * number otherwise and -1 in case of an internal or API error.
5509 */
5510static int
5511xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5512 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005513 xmlSchemaTypePtr ownerItem,
5514 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005515 xmlSchemaTypePtr type,
5516 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005517{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005518 const xmlChar *val;
5519
5520 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005521 return (-1);
5522
Daniel Veillardc0826a72004-08-10 14:17:33 +00005523 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5524 if (value != NULL)
5525 *value = val;
5526
5527 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005528 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005529}
5530
5531/**
5532 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005533 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005534 * @ctxt: a schema parser context
5535 * @node: the element node of the attribute
5536 * @ownerDes: the designation of the parent element
5537 * @ownerItem: the schema object owner if existent
5538 * @ownerElem: the owner element node
5539 * @name: the name of the schema attribute node
5540 * @type: the built-in type to be validated against
5541 * @value: the resulting value if any
5542 *
5543 * Extracts and validates a value against the given built-in type.
5544 * This one is intended to be used internally for validation
5545 * of schema attribute values during parsing of the schema.
5546 *
5547 * Returns 0 if the value is valid, a positive error code
5548 * number otherwise and -1 in case of an internal or API error.
5549 */
5550static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005551xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005552 xmlChar **ownerDes,
5553 xmlSchemaTypePtr ownerItem,
5554 xmlNodePtr ownerElem,
5555 const char *name,
5556 xmlSchemaTypePtr type,
5557 const xmlChar **value)
5558{
5559 xmlAttrPtr attr;
5560
5561 if ((ctxt == NULL) || (type == NULL)) {
5562 if (value != NULL)
5563 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005564 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005565 }
5566 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5567 if (value != NULL)
5568 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005569 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005570 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005571 "Internal error: xmlSchemaPValAttr, the given "
5572 "type '%s' is not a built-in type.\n",
5573 type->name, NULL);
5574 return (-1);
5575 }
5576 attr = xmlSchemaGetPropNode(ownerElem, name);
5577 if (attr == NULL) {
5578 if (value != NULL)
5579 *value = NULL;
5580 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005581 }
5582 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005583 type, value));
5584}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005585
5586static int
5587xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5588 xmlSchemaPtr schema,
5589 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005590 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005591 const xmlChar *namespaceName)
5592{
5593 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005594 return (1);
5595 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5596 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005597 if (pctxt->localImports != NULL) {
5598 int i;
5599 for (i = 0; i < pctxt->nbLocalImports; i++)
5600 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5601 return (1);
5602 }
5603 if (namespaceName == NULL)
5604 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005605 NULL, (xmlSchemaTypePtr) item, node,
5606 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005607 "namespace are not valid, since not indicated by an import "
5608 "statement", NULL);
5609 else
5610 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005611 NULL, (xmlSchemaTypePtr) item, node,
5612 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005613 "namespace '%s' are not valid, since not indicated by an import "
5614 "statement", namespaceName);
5615 return (0);
5616}
5617
Daniel Veillardc0826a72004-08-10 14:17:33 +00005618/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005619 * xmlSchemaParseAttrDecls:
5620 * @ctxt: a schema validation context
5621 * @schema: the schema being built
5622 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005623 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005624 *
5625 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005626 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005627 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5628 */
5629static xmlNodePtr
5630xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5631 xmlNodePtr child, xmlSchemaTypePtr type)
5632{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005633 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005634
Daniel Veillard4255d502002-04-16 15:50:10 +00005635 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005636 (IS_SCHEMA(child, "attributeGroup"))) {
5637 attr = NULL;
5638 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005639 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005640 } else if (IS_SCHEMA(child, "attributeGroup")) {
5641 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005642 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005643 }
5644 if (attr != NULL) {
5645 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005646 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5647 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5648 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005649 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005650 lastattr = attr;
5651 } else {
5652 lastattr->next = attr;
5653 lastattr = attr;
5654 }
5655 }
5656 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005657 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005658 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005659}
5660
5661/**
5662 * xmlSchemaParseAnnotation:
5663 * @ctxt: a schema validation context
5664 * @schema: the schema being built
5665 * @node: a subtree containing XML Schema informations
5666 *
5667 * parse a XML schema Attrribute declaration
5668 * *WARNING* this interface is highly subject to change
5669 *
William M. Bracke7091952004-05-11 15:09:58 +00005670 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005671 * 1 in case of success.
5672 */
5673static xmlSchemaAnnotPtr
5674xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5675 xmlNodePtr node)
5676{
5677 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005678 xmlNodePtr child = NULL;
5679 xmlAttrPtr attr;
5680 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005681
Daniel Veillardc0826a72004-08-10 14:17:33 +00005682 /*
5683 * INFO: S4S completed.
5684 */
5685 /*
5686 * id = ID
5687 * {any attributes with non-schema namespace . . .}>
5688 * Content: (appinfo | documentation)*
5689 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005690 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5691 return (NULL);
5692 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005693 attr = node->properties;
5694 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005695 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005696 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005697 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005698 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005699
5700 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005701 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5702 NULL, NULL, attr);
5703 }
5704 attr = attr->next;
5705 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005706 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005707 /*
5708 * And now for the children...
5709 */
5710 child = node->children;
5711 while (child != NULL) {
5712 if (IS_SCHEMA(child, "appinfo")) {
5713 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005714 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005715 * source = anyURI
5716 * {any attributes with non-schema namespace . . .}>
5717 * Content: ({any})*
5718 */
5719 attr = child->properties;
5720 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005721 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005722 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005723 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005725
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005726 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005727 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5728 NULL, NULL, attr);
5729 }
5730 attr = attr->next;
5731 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005732 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5733 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005734 child = child->next;
5735 } else if (IS_SCHEMA(child, "documentation")) {
5736 /* TODO: make available the content of "documentation". */
5737 /*
5738 * source = anyURI
5739 * {any attributes with non-schema namespace . . .}>
5740 * Content: ({any})*
5741 */
5742 attr = child->properties;
5743 while (attr != NULL) {
5744 if (attr->ns == NULL) {
5745 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005746 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005747 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5748 NULL, NULL, attr);
5749 }
5750 } else {
5751 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5752 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5753 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005754
5755 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005756 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5757 NULL, NULL, attr);
5758 }
5759 }
5760 attr = attr->next;
5761 }
5762 /*
5763 * Attribute "xml:lang".
5764 */
5765 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5766 if (attr != NULL)
5767 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005768 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005769 child = child->next;
5770 } else {
5771 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005772 xmlSchemaPContentErr(ctxt,
5773 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005774 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5775 barked = 1;
5776 child = child->next;
5777 }
5778 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005779
Daniel Veillard4255d502002-04-16 15:50:10 +00005780 return (ret);
5781}
5782
5783/**
5784 * xmlSchemaParseFacet:
5785 * @ctxt: a schema validation context
5786 * @schema: the schema being built
5787 * @node: a subtree containing XML Schema informations
5788 *
5789 * parse a XML schema Facet declaration
5790 * *WARNING* this interface is highly subject to change
5791 *
5792 * Returns the new type structure or NULL in case of error
5793 */
5794static xmlSchemaFacetPtr
5795xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005796 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005797{
5798 xmlSchemaFacetPtr facet;
5799 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005800 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005801
5802 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5803 return (NULL);
5804
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005805 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005806 if (facet == NULL) {
5807 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5808 return (NULL);
5809 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005810 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005811 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005812 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005813 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5814 "Facet %s has no value\n", node->name, NULL);
5815 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005816 return (NULL);
5817 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005818 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005819 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005820 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005821 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005822 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005823 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005825 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005826 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005827 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005830 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005831 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005832 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005833 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005834 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005835 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005836 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005837 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005838 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005839 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5840 } else if (IS_SCHEMA(node, "minLength")) {
5841 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5842 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005843 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5844 "Unknown facet type %s\n", node->name, NULL);
5845 xmlSchemaFreeFacet(facet);
5846 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005847 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005848 xmlSchemaPValAttrID(ctxt, NULL,
5849 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005850 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005851 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5852 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5853 const xmlChar *fixed;
5854
5855 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5856 if (fixed != NULL) {
5857 if (xmlStrEqual(fixed, BAD_CAST "true"))
5858 facet->fixed = 1;
5859 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005860 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005861 child = node->children;
5862
5863 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005864 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5865 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005866 }
5867 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005868 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5869 "Facet %s has unexpected child content\n",
5870 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005871 }
5872 return (facet);
5873}
5874
5875/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005876 * xmlSchemaParseWildcardNs:
5877 * @ctxt: a schema parser context
5878 * @wildc: the wildcard, already created
5879 * @node: a subtree containing XML Schema informations
5880 *
5881 * Parses the attribute "processContents" and "namespace"
5882 * of a xsd:anyAttribute and xsd:any.
5883 * *WARNING* this interface is highly subject to change
5884 *
5885 * Returns 0 if everything goes fine, a positive error code
5886 * if something is not valid and -1 if an internal error occurs.
5887 */
5888static int
5889xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5890 xmlSchemaPtr schema,
5891 xmlSchemaWildcardPtr wildc,
5892 xmlNodePtr node)
5893{
5894 const xmlChar *pc, *ns, *dictnsItem;
5895 int ret = 0;
5896 xmlChar *nsItem;
5897 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5898 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005899
Daniel Veillardc0826a72004-08-10 14:17:33 +00005900 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5901 if ((pc == NULL)
5902 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5903 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5904 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5905 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5906 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5907 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5908 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005909 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005910 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005911 NULL, node,
5912 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005913 NULL, NULL, NULL);
5914 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005915 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005916 }
5917 /*
5918 * Build the namespace constraints.
5919 */
5920 attr = xmlSchemaGetPropNode(node, "namespace");
5921 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005922 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005923 wildc->any = 1;
5924 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5925 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005926 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005927 return (-1);
5928 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005929 wildc->negNsSet->value = schema->targetNamespace;
5930 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005931 const xmlChar *end, *cur;
5932
5933 cur = ns;
5934 do {
5935 while (IS_BLANK_CH(*cur))
5936 cur++;
5937 end = cur;
5938 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5939 end++;
5940 if (end == cur)
5941 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005942 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005943 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5944 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005945 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005946 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005947 NULL, (xmlNodePtr) attr,
5948 NULL,
5949 "((##any | ##other) | List of (xs:anyURI | "
5950 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005951 nsItem, NULL, NULL, NULL);
5952 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5953 } else {
5954 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5955 dictnsItem = schema->targetNamespace;
5956 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5957 dictnsItem = NULL;
5958 } else {
5959 /*
5960 * Validate the item (anyURI).
5961 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005962 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005963 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5964 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5965 }
5966 /*
5967 * Avoid dublicate namespaces.
5968 */
5969 tmp = wildc->nsSet;
5970 while (tmp != NULL) {
5971 if (dictnsItem == tmp->value)
5972 break;
5973 tmp = tmp->next;
5974 }
5975 if (tmp == NULL) {
5976 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5977 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005978 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005979 return (-1);
5980 }
5981 tmp->value = dictnsItem;
5982 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005983 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005984 wildc->nsSet = tmp;
5985 else
5986 lastNs->next = tmp;
5987 lastNs = tmp;
5988 }
5989
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005990 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005991 xmlFree(nsItem);
5992 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005993 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005994 }
5995 return (ret);
5996}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997
5998static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005999xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6000 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006001 xmlNodePtr node,
6002 int minOccurs,
6003 int maxOccurs) {
6004
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006005 if ((maxOccurs == 0) && ( minOccurs == 0))
6006 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006007 if (maxOccurs != UNBOUNDED) {
6008 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006009 * TODO: Maybe we should better not create the particle,
6010 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006011 * content model.
6012 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006013 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006014 * 3.9.6 Schema Component Constraint: Particle Correct
6015 *
6016 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006017 if (maxOccurs < 1) {
6018 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006019 * 2.2 {max occurs} must be greater than or equal to 1.
6020 */
6021 xmlSchemaPCustomAttrErr(ctxt,
6022 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006023 NULL, NULL,
6024 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006025 "The value must be greater than or equal to 1");
6026 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6027 } else if (minOccurs > maxOccurs) {
6028 /*
6029 * 2.1 {min occurs} must not be greater than {max occurs}.
6030 */
6031 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006032 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006033 NULL, NULL,
6034 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006035 "The value must not be greater than the value of 'maxOccurs'");
6036 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6037 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006038 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006039 return (0);
6040}
6041
Daniel Veillardc0826a72004-08-10 14:17:33 +00006042/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006043 * xmlSchemaParseAny:
6044 * @ctxt: a schema validation context
6045 * @schema: the schema being built
6046 * @node: a subtree containing XML Schema informations
6047 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006048 * Parsea a XML schema <any> element. A particle and wildcard
6049 * will be created (except if minOccurs==maxOccurs==0, in this case
6050 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 * *WARNING* this interface is highly subject to change
6052 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006053 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006054 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006055static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006056xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6057 xmlNodePtr node)
6058{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006059 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006060 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006061 xmlSchemaWildcardPtr wild;
6062 int min, max;
6063 xmlAttrPtr attr;
6064 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006065
6066 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6067 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006068 /*
6069 * Check for illegal attributes.
6070 */
6071 attr = node->properties;
6072 while (attr != NULL) {
6073 if (attr->ns == NULL) {
6074 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6075 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6076 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6077 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6078 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006079 xmlSchemaPIllegalAttrErr(ctxt,
6080 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6081 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006082 }
6083 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006084 xmlSchemaPIllegalAttrErr(ctxt,
6085 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6086 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006087 }
6088 attr = attr->next;
6089 }
6090 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6091 /*
6092 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006093 */
6094 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6095 "(xs:nonNegativeInteger | unbounded)");
6096 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6097 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006098 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6099 /*
6100 * Create & parse the wildcard.
6101 */
6102 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6103 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006104 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006105 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006106 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006107 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006108 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006109 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006110 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006111 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006112 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006113 }
6114 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006115 xmlSchemaPContentErr(ctxt,
6116 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006117 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006118 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006119 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006120 /*
6121 * No component if minOccurs==maxOccurs==0.
6122 */
6123 if ((min == 0) && (max == 0)) {
6124 /* Don't free the wildcard, since it's already on the list. */
6125 return (NULL);
6126 }
6127 /*
6128 * Create the particle.
6129 */
6130 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6131 if (particle == NULL)
6132 return (NULL);
6133 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006134 wild->minOccurs = min;
6135 wild->maxOccurs = max;
6136 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006137
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006138 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006139}
6140
6141/**
6142 * xmlSchemaParseNotation:
6143 * @ctxt: a schema validation context
6144 * @schema: the schema being built
6145 * @node: a subtree containing XML Schema informations
6146 *
6147 * parse a XML schema Notation declaration
6148 *
6149 * Returns the new structure or NULL in case of error
6150 */
6151static xmlSchemaNotationPtr
6152xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006153 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006154{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006155 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006156 xmlSchemaNotationPtr ret;
6157 xmlNodePtr child = NULL;
6158
6159 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6160 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006161 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006162 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006163 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6164 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006165 return (NULL);
6166 }
6167 ret = xmlSchemaAddNotation(ctxt, schema, name);
6168 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006169 return (NULL);
6170 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006171 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006172
6173 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6174 node, BAD_CAST "id");
6175
6176 if (IS_SCHEMA(child, "annotation")) {
6177 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6178 child = child->next;
6179 }
6180
Daniel Veillard4255d502002-04-16 15:50:10 +00006181 child = node->children;
6182 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006183 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6184 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006185 }
6186 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006187 xmlSchemaPContentErr(ctxt,
6188 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006189 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006190 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006191 }
6192
6193 return (ret);
6194}
6195
6196/**
6197 * xmlSchemaParseAnyAttribute:
6198 * @ctxt: a schema validation context
6199 * @schema: the schema being built
6200 * @node: a subtree containing XML Schema informations
6201 *
6202 * parse a XML schema AnyAttrribute declaration
6203 * *WARNING* this interface is highly subject to change
6204 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006205 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006206 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006207static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006208xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6209 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006210{
Daniel Veillard3646d642004-06-02 19:19:14 +00006211 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006212 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006213 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006214
6215 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6216 return (NULL);
6217
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006218 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6219 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006220 if (ret == NULL) {
6221 return (NULL);
6222 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006223 /*
6224 * Check for illegal attributes.
6225 */
6226 attr = node->properties;
6227 while (attr != NULL) {
6228 if (attr->ns == NULL) {
6229 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6230 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6231 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006232 xmlSchemaPIllegalAttrErr(ctxt,
6233 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6234 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006235 }
6236 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006237 xmlSchemaPIllegalAttrErr(ctxt,
6238 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6239 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006240 }
6241 attr = attr->next;
6242 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006243 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6244 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006245 /*
6246 * Parse the namespace list.
6247 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006248 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006249 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006250 /*
6251 * And now for the children...
6252 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006253 child = node->children;
6254 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006255 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6256 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006257 }
6258 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006259 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006260 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006261 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006262 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006263 }
6264
6265 return (ret);
6266}
6267
6268
6269/**
6270 * xmlSchemaParseAttribute:
6271 * @ctxt: a schema validation context
6272 * @schema: the schema being built
6273 * @node: a subtree containing XML Schema informations
6274 *
6275 * parse a XML schema Attrribute declaration
6276 * *WARNING* this interface is highly subject to change
6277 *
William M. Bracke7091952004-05-11 15:09:58 +00006278 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006279 */
6280static xmlSchemaAttributePtr
6281xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006282 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006283{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006284 const xmlChar *name, *attrValue;
6285 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006286 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006287 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006288 xmlAttrPtr attr, nameAttr;
6289 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006290
6291 /*
6292 * Note that the w3c spec assumes the schema to be validated with schema
6293 * for schemas beforehand.
6294 *
6295 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006296 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006297
6298 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6299 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 attr = xmlSchemaGetPropNode(node, "ref");
6301 nameAttr = xmlSchemaGetPropNode(node, "name");
6302
6303 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006304 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006305 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006306 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006307 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006308 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6309 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006310 "One of the attributes 'ref' or 'name' must be present");
6311 return (NULL);
6312 }
6313 if ((topLevel) || (attr == NULL)) {
6314 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006315 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6316 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006317 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006318 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006319 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006320 isRef = 1;
6321
Daniel Veillardc0826a72004-08-10 14:17:33 +00006322 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006323 char buf[50];
6324 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006325
6326 /*
6327 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006328 */
6329 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6330 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6331 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006332 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006333 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006334 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006335 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006336 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006337 if (ret == NULL) {
6338 if (repName != NULL)
6339 xmlFree(repName);
6340 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006341 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006342 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6343 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006344 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006345 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006346 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6347 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006348 /*
6349 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6350 */
6351 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006352 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6353 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006354 "ref", "name");
6355 /*
6356 * Check for illegal attributes.
6357 */
6358 attr = node->properties;
6359 while (attr != NULL) {
6360 if (attr->ns == NULL) {
6361 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6362 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006363 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006364 * 3.2.3 : 3.2
6365 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006366 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006367 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006368 xmlSchemaPIllegalAttrErr(ctxt,
6369 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006370 (xmlSchemaTypePtr) ret, attr);
6371 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6372 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6373 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006374 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6375 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006376 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006377 xmlSchemaPIllegalAttrErr(ctxt,
6378 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6379 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006380 }
6381 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006382 xmlSchemaPIllegalAttrErr(ctxt,
6383 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6384 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006385 }
6386 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006387 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006388 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006389 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006390
Daniel Veillardc0826a72004-08-10 14:17:33 +00006391 /*
6392 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006393 */
6394 if (xmlSchemaPValAttrNode(ctxt,
6395 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006396 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6397 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006398 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006399 /*
6400 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6401 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006402 /*
6403 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6404 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006405 */
6406 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006407 xmlSchemaPSimpleTypeErr(ctxt,
6408 XML_SCHEMAP_NO_XMLNS,
6409 NULL, (xmlNodePtr) nameAttr,
6410 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6411 "The value of type 'xs:NCName' must not match 'xmlns'",
6412 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006413 if (repName != NULL)
6414 xmlFree(repName);
6415 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006416 }
6417 /*
6418 * Evaluate the target namespace
6419 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006420 if (topLevel) {
6421 ns = schema->targetNamespace;
6422 } else {
6423 attr = xmlSchemaGetPropNode(node, "form");
6424 if (attr != NULL) {
6425 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6426 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6427 ns = schema->targetNamespace;
6428 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006429 xmlSchemaPSimpleTypeErr(ctxt,
6430 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6431 NULL, (xmlNodePtr) attr,
6432 NULL, "(qualified | unqualified)",
6433 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006434 }
6435 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006436 ns = schema->targetNamespace;
6437 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006438 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006439 if (ret == NULL) {
6440 if (repName != NULL)
6441 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006442 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006443 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006444 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006445 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006446 if (topLevel)
6447 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006448 /*
6449 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6450 * TODO: Move this to the component layer.
6451 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006452 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006453 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006454 XML_SCHEMAP_NO_XSI,
6455 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006456 "The target namespace must not match '%s'",
6457 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 }
6459 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006460 * Check for illegal attributes.
6461 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006462 attr = node->properties;
6463 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006464 if (attr->ns == NULL) {
6465 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6466 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6467 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006468 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6469 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006470 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6472 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006473 xmlSchemaPIllegalAttrErr(ctxt,
6474 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6475 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006476 }
6477 }
6478 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006479 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6480 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 }
6482 attr = attr->next;
6483 }
6484 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006485 node, "type", &ret->typeNs, &ret->typeName);
6486 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006487 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6488 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006489 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006490 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006491 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6493 if (ret->defValue != NULL)
6494 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006495 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006496 * Attribute "default".
6497 */
6498 attr = xmlSchemaGetPropNode(node, "default");
6499 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006500 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006501 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006502 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006503 */
6504 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6505 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6506 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6507 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006508 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6509 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006510 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006511 /*
6512 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006513 */
6514 attr = xmlSchemaGetPropNode(node, "use");
6515 if (attr != NULL) {
6516 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6517 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6518 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6519 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6520 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6521 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6522 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6523 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006524 xmlSchemaPSimpleTypeErr(ctxt,
6525 XML_SCHEMAP_INVALID_ATTR_USE,
6526 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6527 NULL, "(optional | prohibited | required)",
6528 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006529 } else
6530 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006531 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006532 * 3.2.3 : 2
6533 * If default and use are both present, use must have
6534 * the actual value optional.
6535 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6537 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006538 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006539 xmlSchemaPSimpleTypeErr(ctxt,
6540 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6541 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6542 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006543 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006544 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006545 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 /*
6548 * And now for the children...
6549 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006550 child = node->children;
6551 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006552 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6553 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006554 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006555 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006556 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006558 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 * 3.2.3 : 3.2
6560 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006561 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006562 */
6563 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6564 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6565 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006566 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6568 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006569 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006570 }
6571 } else {
6572 if (IS_SCHEMA(child, "simpleType")) {
6573 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006574 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006575 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006576 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006577 */
6578 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6579 &repName, (xmlSchemaTypePtr) ret, node, child,
6580 "The attribute 'type' and the <simpleType> child "
6581 "are mutually exclusive", NULL);
6582 } else
6583 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6584 child = child->next;
6585 }
6586 if (child != NULL)
6587 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6588 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6589 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006590 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006591 /*
6592 * Cleanup.
6593 */
6594 if (repName != NULL)
6595 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006596 return (ret);
6597}
6598
6599/**
6600 * xmlSchemaParseAttributeGroup:
6601 * @ctxt: a schema validation context
6602 * @schema: the schema being built
6603 * @node: a subtree containing XML Schema informations
6604 *
6605 * parse a XML schema Attribute Group declaration
6606 * *WARNING* this interface is highly subject to change
6607 *
6608 * Returns the attribute group or NULL in case of error.
6609 */
6610static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006611xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006612 xmlSchemaPtr schema, xmlNodePtr node,
6613 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006614{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006615 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006616 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006617 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006618 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006619 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006620
6621 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6622 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006623
6624 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006625 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006626 if ((topLevel) || (attr == NULL)) {
6627 /*
6628 * Parse as an attribute group definition.
6629 * Note that those are allowed at top level only.
6630 */
6631 if (nameAttr == NULL) {
6632 xmlSchemaPMissingAttrErr(ctxt,
6633 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006634 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006635 return (NULL);
6636 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006637 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006638 * (xmlNodePtr) nameAttr);
6639 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006640 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006641 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006642 */
6643 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006644 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006645 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6646 return (NULL);
6647 }
6648 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6649 if (ret == NULL)
6650 return (NULL);
6651 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6652 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6653 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006654 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006655 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006656 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006657 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006658
6659 /*
6660 * Parse as an attribute group definition reference.
6661 */
6662 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006663 xmlSchemaPMissingAttrErr(ctxt,
6664 XML_SCHEMAP_S4S_ATTR_MISSING,
6665 NULL, node, "ref", NULL);
6666 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006667 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006668 NULL, NULL, attr, &refNs,&ref);
6669
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006670 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006671 name = (const xmlChar *) buf;
6672 if (name == NULL) {
6673 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6674 "attribute group definition reference", node);
6675 return (NULL);
6676 }
6677 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6678 if (ret == NULL)
6679 return (NULL);
6680 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6681 ret->ref = ref;
6682 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006683 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006684 xmlSchemaCheckReference(ctxt, schema, node,
6685 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006686 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006687 /*
6688 * Check for illegal attributes.
6689 */
6690 attr = node->properties;
6691 while (attr != NULL) {
6692 if (attr->ns == NULL) {
6693 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6694 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006695 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006696 {
6697 xmlSchemaPIllegalAttrErr(ctxt,
6698 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6699 NULL, NULL, attr);
6700 }
6701 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6702 xmlSchemaPIllegalAttrErr(ctxt,
6703 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6704 NULL, NULL, attr);
6705 }
6706 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006707 }
6708 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006709 /*
6710 * And now for the children...
6711 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006712 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006713 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006714 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006715 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006716 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6717 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006718 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006719 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006720 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006721 if (IS_SCHEMA(child, "anyAttribute")) {
6722 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6723 child = child->next;
6724 }
6725 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006726 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006727 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006728 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6729 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006730 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006731 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006732 ctxt->container = oldcontainer;
6733 return (ret);
6734}
6735
6736/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006737 * xmlSchemaPValAttrFormDefault:
6738 * @value: the value
6739 * @flags: the flags to be modified
6740 * @flagQualified: the specific flag for "qualified"
6741 *
6742 * Returns 0 if the value is valid, 1 otherwise.
6743 */
6744static int
6745xmlSchemaPValAttrFormDefault(const xmlChar *value,
6746 int *flags,
6747 int flagQualified)
6748{
6749 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6750 if ((*flags & flagQualified) == 0)
6751 *flags |= flagQualified;
6752 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006753 return (1);
6754
William M. Brack2f2a6632004-08-20 23:09:47 +00006755 return (0);
6756}
6757
6758/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006759 * xmlSchemaPValAttrBlockFinal:
6760 * @value: the value
6761 * @flags: the flags to be modified
6762 * @flagAll: the specific flag for "#all"
6763 * @flagExtension: the specific flag for "extension"
6764 * @flagRestriction: the specific flag for "restriction"
6765 * @flagSubstitution: the specific flag for "substitution"
6766 * @flagList: the specific flag for "list"
6767 * @flagUnion: the specific flag for "union"
6768 *
6769 * Validates the value of the attribute "final" and "block". The value
6770 * is converted into the specified flag values and returned in @flags.
6771 *
6772 * Returns 0 if the value is valid, 1 otherwise.
6773 */
6774
6775static int
6776xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006777 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006778 int flagAll,
6779 int flagExtension,
6780 int flagRestriction,
6781 int flagSubstitution,
6782 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006783 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006784{
6785 int ret = 0;
6786
6787 /*
6788 * TODO: This does not check for dublicate entries.
6789 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006790 if ((flags == NULL) || (value == NULL))
6791 return (-1);
6792 if (value[0] == 0)
6793 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006794 if (xmlStrEqual(value, BAD_CAST "#all")) {
6795 if (flagAll != -1)
6796 *flags |= flagAll;
6797 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006798 if (flagExtension != -1)
6799 *flags |= flagExtension;
6800 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006801 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006803 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006804 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006805 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006806 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006807 *flags |= flagUnion;
6808 }
6809 } else {
6810 const xmlChar *end, *cur = value;
6811 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006812
Daniel Veillardc0826a72004-08-10 14:17:33 +00006813 do {
6814 while (IS_BLANK_CH(*cur))
6815 cur++;
6816 end = cur;
6817 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6818 end++;
6819 if (end == cur)
6820 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006821 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006822 if (xmlStrEqual(item, BAD_CAST "extension")) {
6823 if (flagExtension != -1) {
6824 if ((*flags & flagExtension) == 0)
6825 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006826 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006827 ret = 1;
6828 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6829 if (flagRestriction != -1) {
6830 if ((*flags & flagRestriction) == 0)
6831 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006832 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006833 ret = 1;
6834 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6835 if (flagSubstitution != -1) {
6836 if ((*flags & flagSubstitution) == 0)
6837 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006838 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006839 ret = 1;
6840 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6841 if (flagList != -1) {
6842 if ((*flags & flagList) == 0)
6843 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006844 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006845 ret = 1;
6846 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6847 if (flagUnion != -1) {
6848 if ((*flags & flagUnion) == 0)
6849 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006850 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006851 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006852 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006853 ret = 1;
6854 if (item != NULL)
6855 xmlFree(item);
6856 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006857 } while ((ret == 0) && (*cur != 0));
6858 }
6859
Daniel Veillardc0826a72004-08-10 14:17:33 +00006860 return (ret);
6861}
6862
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006863static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006864xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006865 xmlSchemaIDCPtr idc,
6866 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006867 xmlAttrPtr attr,
6868 int isField)
6869{
6870 xmlNodePtr node;
6871
6872 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006873 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006874 * Schema Component Constraint: Selector Value OK
6875 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006876 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006877 * in [XPath].
6878 */
6879 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006880 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006881 XML_SCHEMAP_INTERNAL,
6882 "Internal error: xmlSchemaCheckCSelectorXPath, "
6883 "the selector is not specified.\n", NULL, NULL);
6884 return (-1);
6885 }
6886 if (attr == NULL)
6887 node = idc->node;
6888 else
6889 node = (xmlNodePtr) attr;
6890 if (selector->xpath == NULL) {
6891 xmlSchemaPCustomErr(ctxt,
6892 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006893 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6894 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006895 "The XPath expression of the selector is not valid", NULL);
6896 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6897 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006898 const xmlChar **nsArray = NULL;
6899 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006900 /*
6901 * Compile the XPath expression.
6902 */
6903 /*
6904 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006905 * TODO: Call xmlPatterncompile with different options for selector/
6906 * field.
6907 */
6908 nsList = xmlGetNsList(attr->doc, attr->parent);
6909 /*
6910 * Build an array of prefixes and namespaces.
6911 */
6912 if (nsList != NULL) {
6913 int i, count = 0;
6914 xmlNsPtr ns;
6915
6916 for (i = 0; nsList[i] != NULL; i++)
6917 count++;
6918
6919 nsArray = (const xmlChar **) xmlMalloc(
6920 (count * 2 + 1) * sizeof(const xmlChar *));
6921 if (nsArray == NULL) {
6922 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6923 NULL);
6924 return (-1);
6925 }
6926 for (i = 0; i < count; i++) {
6927 ns = nsList[i];
6928 nsArray[2 * i] = nsList[i]->href;
6929 nsArray[2 * i + 1] = nsList[i]->prefix;
6930 }
6931 nsArray[count * 2] = NULL;
6932 xmlFree(nsList);
6933 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006934 /*
6935 * TODO: Differentiate between "selector" and "field".
6936 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006937 if (isField)
6938 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006939 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006940 else
6941 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006942 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006943 if (nsArray != NULL)
6944 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006945
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006946 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006947 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006948 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006949 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6950 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006951 "The XPath expression '%s' could not be "
6952 "compiled", selector->xpath);
6953 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006954 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006955 }
6956 return (0);
6957}
6958
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006959#define ADD_ANNOTATION(annot) \
6960 xmlSchemaAnnotPtr cur = item->annot; \
6961 if (item->annot == NULL) { \
6962 item->annot = annot; \
6963 return (annot); \
6964 } \
6965 cur = item->annot; \
6966 if (cur->next != NULL) { \
6967 cur = cur->next; \
6968 } \
6969 cur->next = annot;
6970
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006971/**
6972 * xmlSchemaAssignAnnotation:
6973 * @item: the schema component
6974 * @annot: the annotation
6975 *
6976 * Adds the annotation to the given schema component.
6977 *
6978 * Returns the given annotaion.
6979 */
6980static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006981xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6982 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006983{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006984 if ((annItem == NULL) || (annot == NULL))
6985 return (NULL);
6986 switch (annItem->type) {
6987 case XML_SCHEMA_TYPE_ELEMENT: {
6988 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6989 ADD_ANNOTATION(annot)
6990 }
6991 break;
6992 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6993 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6994 ADD_ANNOTATION(annot)
6995 }
6996 break;
6997 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6998 case XML_SCHEMA_TYPE_ANY: {
6999 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7000 ADD_ANNOTATION(annot)
7001 }
7002 break;
7003 case XML_SCHEMA_TYPE_PARTICLE:
7004 case XML_SCHEMA_TYPE_IDC_KEY:
7005 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007006 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007007 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7008 ADD_ANNOTATION(annot)
7009 }
7010 break;
7011 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7012 xmlSchemaAttributeGroupPtr item =
7013 (xmlSchemaAttributeGroupPtr) annItem;
7014 ADD_ANNOTATION(annot)
7015 }
7016 break;
7017 case XML_SCHEMA_TYPE_NOTATION: {
7018 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7019 ADD_ANNOTATION(annot)
7020 }
7021 break;
7022 case XML_SCHEMA_FACET_MININCLUSIVE:
7023 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7024 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7025 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7026 case XML_SCHEMA_FACET_TOTALDIGITS:
7027 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7028 case XML_SCHEMA_FACET_PATTERN:
7029 case XML_SCHEMA_FACET_ENUMERATION:
7030 case XML_SCHEMA_FACET_WHITESPACE:
7031 case XML_SCHEMA_FACET_LENGTH:
7032 case XML_SCHEMA_FACET_MAXLENGTH:
7033 case XML_SCHEMA_FACET_MINLENGTH: {
7034 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7035 ADD_ANNOTATION(annot)
7036 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007037 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007038 case XML_SCHEMA_TYPE_SIMPLE:
7039 case XML_SCHEMA_TYPE_COMPLEX: {
7040 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7041 ADD_ANNOTATION(annot)
7042 }
7043 break;
7044 case XML_SCHEMA_TYPE_GROUP: {
7045 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7046 ADD_ANNOTATION(annot)
7047 }
7048 break;
7049 case XML_SCHEMA_TYPE_SEQUENCE:
7050 case XML_SCHEMA_TYPE_CHOICE:
7051 case XML_SCHEMA_TYPE_ALL: {
7052 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7053 ADD_ANNOTATION(annot)
7054 }
7055 break;
7056 default:
7057 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007058 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007059 NULL, NULL, NULL,
7060 "Internal error: xmlSchemaAddAnnotation, "
7061 "The item is not a annotated schema component", NULL);
7062 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007063 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007064 return (annot);
7065}
7066
7067/**
7068 * xmlSchemaParseIDCSelectorAndField:
7069 * @ctxt: a schema validation context
7070 * @schema: the schema being built
7071 * @node: a subtree containing XML Schema informations
7072 *
7073 * Parses a XML Schema identity-contraint definition's
7074 * <selector> and <field> elements.
7075 *
7076 * Returns the parsed identity-constraint definition.
7077 */
7078static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007079xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007080 xmlSchemaPtr schema,
7081 xmlSchemaIDCPtr idc,
7082 xmlNodePtr node,
7083 int isField)
7084{
7085 xmlSchemaIDCSelectPtr item;
7086 xmlNodePtr child = NULL;
7087 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007088
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007089 /*
7090 * Check for illegal attributes.
7091 */
7092 attr = node->properties;
7093 while (attr != NULL) {
7094 if (attr->ns == NULL) {
7095 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7096 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007097 xmlSchemaPIllegalAttrErr(ctxt,
7098 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7099 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007100 }
7101 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007102 xmlSchemaPIllegalAttrErr(ctxt,
7103 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7104 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007105 }
7106 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007107 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007108 /*
7109 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007110 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007111 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7112 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007113 xmlSchemaPErrMemory(ctxt,
7114 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007115 NULL);
7116 return (NULL);
7117 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007118 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007119 /*
7120 * Attribute "xpath" (mandatory).
7121 */
7122 attr = xmlSchemaGetPropNode(node, "xpath");
7123 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007124 xmlSchemaPMissingAttrErr(ctxt,
7125 XML_SCHEMAP_S4S_ATTR_MISSING,
7126 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007127 "name", NULL);
7128 } else {
7129 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7130 /*
7131 * URGENT TODO: "field"s have an other syntax than "selector"s.
7132 */
7133
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007134 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7135 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007136 xmlSchemaPErr(ctxt,
7137 (xmlNodePtr) attr,
7138 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007139 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007140 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007141 NULL, NULL);
7142 }
7143
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007144 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007145 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007146 /*
7147 * And now for the children...
7148 */
7149 child = node->children;
7150 if (IS_SCHEMA(child, "annotation")) {
7151 /*
7152 * Add the annotation to the parent IDC.
7153 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007154 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007155 xmlSchemaParseAnnotation(ctxt, schema, child));
7156 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007157 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007158 if (child != NULL) {
7159 xmlSchemaPContentErr(ctxt,
7160 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007161 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007162 NULL, "(annotation?)");
7163 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007164
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007165 return (item);
7166}
7167
7168/**
7169 * xmlSchemaParseIDC:
7170 * @ctxt: a schema validation context
7171 * @schema: the schema being built
7172 * @node: a subtree containing XML Schema informations
7173 *
7174 * Parses a XML Schema identity-contraint definition.
7175 *
7176 * Returns the parsed identity-constraint definition.
7177 */
7178static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007179xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007180 xmlSchemaPtr schema,
7181 xmlNodePtr node,
7182 xmlSchemaTypeType idcCategory,
7183 const xmlChar *targetNamespace)
7184{
7185 xmlSchemaIDCPtr item = NULL;
7186 xmlNodePtr child = NULL;
7187 xmlAttrPtr attr;
7188 const xmlChar *name = NULL;
7189 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7190 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007191
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007192 /*
7193 * Check for illegal attributes.
7194 */
7195 attr = node->properties;
7196 while (attr != NULL) {
7197 if (attr->ns == NULL) {
7198 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7199 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7200 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7201 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007202 xmlSchemaPIllegalAttrErr(ctxt,
7203 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7204 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007205 }
7206 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007207 xmlSchemaPIllegalAttrErr(ctxt,
7208 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7209 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007210 }
7211 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007212 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007213 /*
7214 * Attribute "name" (mandatory).
7215 */
7216 attr = xmlSchemaGetPropNode(node, "name");
7217 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007218 xmlSchemaPMissingAttrErr(ctxt,
7219 XML_SCHEMAP_S4S_ATTR_MISSING,
7220 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007221 "name", NULL);
7222 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007223 } else if (xmlSchemaPValAttrNode(ctxt,
7224 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007225 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7226 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007227 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007228 /*
7229 * Create the component.
7230 */
7231 if (schema->idcDef == NULL)
7232 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007233 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007234 return (NULL);
7235
7236 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7237 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007238 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007239 "allocating an identity-constraint definition", NULL);
7240 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007241 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007242 /*
7243 * Add the IDC to the list of IDCs on the schema component.
7244 */
7245 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007246 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007247 xmlSchemaPCustomErrExt(ctxt,
7248 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007249 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007250 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007251 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007252 name, targetNamespace, NULL);
7253 xmlFree(item);
7254 return (NULL);
7255 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007256 memset(item, 0, sizeof(xmlSchemaIDC));
7257 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007258 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007259 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007260 if (ctxt->assemble != NULL)
7261 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007262 /*
7263 * The target namespace of the parent element declaration.
7264 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007265 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007266 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7267 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007268 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7269 /*
7270 * Attribute "refer" (mandatory).
7271 */
7272 attr = xmlSchemaGetPropNode(node, "refer");
7273 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007274 xmlSchemaPMissingAttrErr(ctxt,
7275 XML_SCHEMAP_S4S_ATTR_MISSING,
7276 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007277 "refer", NULL);
7278 } else {
7279 /*
7280 * Create a reference item.
7281 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007282 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007283 NULL, NULL);
7284 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007285 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007286 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007287 NULL, NULL, attr,
7288 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007289 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007290 xmlSchemaCheckReference(ctxt, schema, node,
7291 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007292 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007293 }
7294 }
7295 /*
7296 * And now for the children...
7297 */
7298 child = node->children;
7299 if (IS_SCHEMA(child, "annotation")) {
7300 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7301 child = child->next;
7302 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007303 if (child == NULL) {
7304 xmlSchemaPContentErr(ctxt,
7305 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007306 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007307 "A child element is missing",
7308 "(annotation?, (selector, field+))");
7309 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007310 /*
7311 * Child element <selector>.
7312 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007313 if (IS_SCHEMA(child, "selector")) {
7314 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007315 item, child, 0);
7316 child = child->next;
7317 /*
7318 * Child elements <field>.
7319 */
7320 if (IS_SCHEMA(child, "field")) {
7321 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007322 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007323 item, child, 1);
7324 if (field != NULL) {
7325 field->index = item->nbFields;
7326 item->nbFields++;
7327 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007328 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007329 else
7330 item->fields = field;
7331 lastField = field;
7332 }
7333 child = child->next;
7334 } while (IS_SCHEMA(child, "field"));
7335 } else {
7336 xmlSchemaPContentErr(ctxt,
7337 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007338 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007339 NULL, "(annotation?, (selector, field+))");
7340 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007341 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007342 if (child != NULL) {
7343 xmlSchemaPContentErr(ctxt,
7344 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007345 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007346 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007347 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007348
7349 return (item);
7350}
7351
Daniel Veillardc0826a72004-08-10 14:17:33 +00007352/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007353 * xmlSchemaParseElement:
7354 * @ctxt: a schema validation context
7355 * @schema: the schema being built
7356 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007357 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007358 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007359 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007360 * *WARNING* this interface is highly subject to change
7361 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007362 * Returns the element declaration or a particle; NULL in case
7363 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007364 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007365static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007366xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007367 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007368{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007369 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007370 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007371 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007372 xmlNodePtr child = NULL;
7373 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007374 int min, max, isRef = 0;
7375 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007376
7377 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7378 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007379
Daniel Veillard4255d502002-04-16 15:50:10 +00007380 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007381 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007382 /*
7383 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007384 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007385 * robust.
7386 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007387 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007388 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007389 if ((topLevel) || (attr == NULL)) {
7390 if (nameAttr == NULL) {
7391 xmlSchemaPMissingAttrErr(ctxt,
7392 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007393 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007394 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007395 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007396 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007397 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007398
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007399 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007400 child = node->children;
7401 if (IS_SCHEMA(child, "annotation")) {
7402 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7403 child = child->next;
7404 }
7405 /*
7406 * Skip particle part if a global declaration.
7407 */
7408 if (topLevel)
7409 goto declaration_part;
7410 /*
7411 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007412 */
7413 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7414 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7415 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007416 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7417 if (particle == NULL)
7418 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007419
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007420 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7421
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007422 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007423 const xmlChar *refNs = NULL, *ref = NULL;
7424 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007425 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007426 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007427 */
7428 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007429 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007430 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007431 /*
7432 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007433 */
7434 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007435 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007436 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007437 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007438 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007439 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007440 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007441 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007442 attr = node->properties;
7443 while (attr != NULL) {
7444 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007445 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7446 xmlStrEqual(attr->name, BAD_CAST "name") ||
7447 xmlStrEqual(attr->name, BAD_CAST "id") ||
7448 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7449 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7450 {
7451 attr = attr->next;
7452 continue;
7453 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007454 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007455 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007456 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007457 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007458 "Only the attributes 'minOccurs', 'maxOccurs' and "
7459 "'id' are allowed in addition to 'ref'");
7460 break;
7461 }
7462 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7463 xmlSchemaPIllegalAttrErr(ctxt,
7464 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007465 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007466 }
7467 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007468 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007469 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007470 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007471 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007472 if (child != NULL) {
7473 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7474 NULL, NULL, node, child, NULL, "(annotation?)");
7475 }
7476 if ((min == 0) && (max == 0))
7477 goto return_null;
7478 /*
7479 * Create the reference item.
7480 */
7481 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7482 ref, refNs);
7483 if (refer == NULL)
7484 goto return_null;
7485 particle->children = (xmlSchemaTreeItemPtr) refer;
7486 particle->annot = annot;
7487 /*
7488 * Add to assembled items; the reference need to be resolved.
7489 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007490 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007491 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7492
7493 return ((xmlSchemaBasicItemPtr) particle);
7494 }
7495 /*
7496 * The declaration part ===============================================
7497 */
7498declaration_part:
7499 {
7500 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7501 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7502
7503 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007504 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007505 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007506 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007507 * Evaluate the target namespace.
7508 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007509 if (topLevel) {
7510 ns = schema->targetNamespace;
7511 } else {
7512 attr = xmlSchemaGetPropNode(node, "form");
7513 if (attr != NULL) {
7514 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7515 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007516 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007517 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007518 xmlSchemaPSimpleTypeErr(ctxt,
7519 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7520 NULL, (xmlNodePtr) attr,
7521 NULL, "(qualified | unqualified)",
7522 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007523 }
7524 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007525 ns = schema->targetNamespace;
7526 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007527 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007528 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007529 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007530 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007531 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7532 decl->node = node;
7533 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007534 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 * Check for illegal attributes.
7536 */
William M. Bracke7091952004-05-11 15:09:58 +00007537 attr = node->properties;
7538 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007539 if (attr->ns == NULL) {
7540 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7541 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007542 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007543 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007544 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007545 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007546 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7547 {
7548 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007549 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007550 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007551 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007552 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007553 xmlSchemaPIllegalAttrErr(ctxt,
7554 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7555 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007556 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007557 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7558 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007559 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7560
7561 xmlSchemaPIllegalAttrErr(ctxt,
7562 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007563 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007564 }
7565 }
7566 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007567
Daniel Veillardc0826a72004-08-10 14:17:33 +00007568 xmlSchemaPIllegalAttrErr(ctxt,
7569 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007570 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007571 }
7572 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007573 }
William M. Bracke7091952004-05-11 15:09:58 +00007574 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007575 * Extract/validate attributes.
7576 */
7577 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007578 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007579 * Process top attributes of global element declarations here.
7580 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007581 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7582 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007583 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7584 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7585 &(decl->substGroupNs), &(decl->substGroup));
7586 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007587 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007588 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007589 /*
7590 * Attribute "final".
7591 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007592 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007593 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007594 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7595 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7596 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7597 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007598 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007599 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7600 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007601 -1,
7602 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7603 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007604 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007605 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007606 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7607 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007608 attrValue, NULL, NULL, NULL);
7609 }
7610 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007611 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007612 /*
7613 * Attribute "block".
7614 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007615 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007616 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007617 /*
7618 * Apply default "block" values.
7619 */
7620 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7621 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7622 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7623 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7624 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7625 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007626 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007627 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7628 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007629 -1,
7630 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007631 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007632 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7633 xmlSchemaPSimpleTypeErr(ctxt,
7634 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007635 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007636 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007637 "restriction | substitution))", attrValue,
7638 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007639 }
7640 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007641 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007642 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007643 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007644
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007645 attr = xmlSchemaGetPropNode(node, "type");
7646 if (attr != NULL) {
7647 xmlSchemaPValAttrNodeQName(ctxt, schema,
7648 NULL, (xmlSchemaTypePtr) decl, attr,
7649 &(decl->namedTypeNs), &(decl->namedType));
7650 xmlSchemaCheckReference(ctxt, schema, node,
7651 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7652 }
7653 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7654 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007655 if (attr != NULL) {
7656 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007657 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007658 /*
7659 * 3.3.3 : 1
7660 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007661 */
7662 xmlSchemaPMutualExclAttrErr(ctxt,
7663 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007664 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007665 "default", "fixed");
7666 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007667 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7668 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007669 }
William M. Bracke7091952004-05-11 15:09:58 +00007670 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007671 /*
7672 * And now for the children...
7673 */
7674 oldcontainer = ctxt->container;
7675 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007676 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007677 /*
7678 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007679 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007680 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007681 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007682 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007683 xmlSchemaPContentErr(ctxt,
7684 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007685 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007686 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007687 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007688 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007689 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007690 child = child->next;
7691 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007692 /*
7693 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007694 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007695 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007696 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007697 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007698 xmlSchemaPContentErr(ctxt,
7699 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007700 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007701 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007702 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007703 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007704 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007705 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007706 }
William M. Bracke7091952004-05-11 15:09:58 +00007707 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007708 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007709 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007710 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007711 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007712 } else if (IS_SCHEMA(child, "key")) {
7713 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007714 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007715 } else if (IS_SCHEMA(child, "keyref")) {
7716 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007717 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007718 }
7719 if (lastIDC != NULL)
7720 lastIDC->next = curIDC;
7721 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007722 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007723 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007724 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007725 }
7726 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007727 xmlSchemaPContentErr(ctxt,
7728 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007729 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007730 NULL, "(annotation?, ((simpleType | complexType)?, "
7731 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007732 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007733 ctxt->container = oldcontainer;
7734 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007735 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007736 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007737 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007738 * different layer.
7739 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007740 FREE_AND_NULL(des)
7741 if (topLevel)
7742 return ((xmlSchemaBasicItemPtr) decl);
7743 else {
7744 particle->children = (xmlSchemaTreeItemPtr) decl;
7745 return ((xmlSchemaBasicItemPtr) particle);
7746 }
7747
7748return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007749 FREE_AND_NULL(des);
7750 if (annot != NULL) {
7751 if (particle != NULL)
7752 particle->annot = NULL;
7753 if (decl != NULL)
7754 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007755 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007756 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007757 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007758}
7759
7760/**
7761 * xmlSchemaParseUnion:
7762 * @ctxt: a schema validation context
7763 * @schema: the schema being built
7764 * @node: a subtree containing XML Schema informations
7765 *
7766 * parse a XML schema Union definition
7767 * *WARNING* this interface is highly subject to change
7768 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007769 * Returns -1 in case of internal error, 0 in case of success and a positive
7770 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007771 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007772static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007773xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007774 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007775{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007776 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007777 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007778 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007779 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007780
7781 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007782 return (-1);
7783 /* Not a component, don't create it. */
7784 type = ctxt->ctxtType;
7785 /*
7786 * Mark the simple type as being of variety "union".
7787 */
7788 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007789 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007790 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7791 * then the ·simple ur-type definition·."
7792 */
7793 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007794 /*
7795 * Check for illegal attributes.
7796 */
7797 attr = node->properties;
7798 while (attr != NULL) {
7799 if (attr->ns == NULL) {
7800 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7801 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007802 xmlSchemaPIllegalAttrErr(ctxt,
7803 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7804 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007805 }
7806 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007807 xmlSchemaPIllegalAttrErr(ctxt,
7808 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7809 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007810 }
7811 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007812 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007813 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007814 /*
7815 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007816 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007817 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007818 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007819 if (attr != NULL) {
7820 const xmlChar *end;
7821 xmlChar *tmp;
7822 const xmlChar *localName, *nsName;
7823 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7824 xmlSchemaQNameRefPtr ref;
7825
7826 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007827 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007828 do {
7829 while (IS_BLANK_CH(*cur))
7830 cur++;
7831 end = cur;
7832 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7833 end++;
7834 if (end == cur)
7835 break;
7836 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007837 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7838 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007839 /*
7840 * Create the member type link.
7841 */
7842 link = (xmlSchemaTypeLinkPtr)
7843 xmlMalloc(sizeof(xmlSchemaTypeLink));
7844 if (link == NULL) {
7845 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7846 "allocating a type link", NULL);
7847 return (-1);
7848 }
7849 link->type = NULL;
7850 link->next = NULL;
7851 if (lastLink == NULL)
7852 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007853 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007854 lastLink->next = link;
7855 lastLink = link;
7856 /*
7857 * Create a reference item.
7858 */
7859 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7860 localName, nsName);
7861 if (ref == NULL) {
7862 FREE_AND_NULL(tmp)
7863 return (-1);
7864 }
7865 /*
7866 * Assign the reference to the link, it will be resolved
7867 * later during fixup of the union simple type.
7868 */
7869 link->type = (xmlSchemaTypePtr) ref;
7870 }
7871 FREE_AND_NULL(tmp)
7872 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007873 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007874
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007875 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007876 /*
7877 * And now for the children...
7878 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007879 child = node->children;
7880 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007881 /*
7882 * Add the annotation to the simple type ancestor.
7883 */
7884 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7885 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007886 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007887 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007888 if (IS_SCHEMA(child, "simpleType")) {
7889 xmlSchemaTypePtr subtype, last = NULL;
7890
7891 /*
7892 * Anchor the member types in the "subtypes" field of the
7893 * simple type.
7894 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007895 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007896 subtype = (xmlSchemaTypePtr)
7897 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7898 if (subtype != NULL) {
7899 if (last == NULL) {
7900 type->subtypes = subtype;
7901 last = subtype;
7902 } else {
7903 last->next = subtype;
7904 last = subtype;
7905 }
7906 last->next = NULL;
7907 }
7908 child = child->next;
7909 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007910 }
7911 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007912 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007913 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007914 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007915 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007916 if ((attr == NULL) && (type->subtypes == NULL)) {
7917 /*
7918 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007919 * Either the memberTypes [attribute] of the <union> element must
7920 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007921 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007922 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007923 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7924 NULL, NULL, node,
7925 "Either the attribute 'memberTypes' or "
7926 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007927 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007928 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007929}
7930
7931/**
7932 * xmlSchemaParseList:
7933 * @ctxt: a schema validation context
7934 * @schema: the schema being built
7935 * @node: a subtree containing XML Schema informations
7936 *
7937 * parse a XML schema List definition
7938 * *WARNING* this interface is highly subject to change
7939 *
William M. Bracke7091952004-05-11 15:09:58 +00007940 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007941 * 1 in case of success.
7942 */
7943static xmlSchemaTypePtr
7944xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007945 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007946{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007947 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007948 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007949 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007950
7951 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7952 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007953 /* Not a component, don't create it. */
7954 type = ctxt->ctxtType;
7955 /*
7956 * Mark the type as being of variety "list".
7957 */
7958 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007959 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007960 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7961 * then the ·simple ur-type definition·."
7962 */
7963 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007964 /*
7965 * Check for illegal attributes.
7966 */
7967 attr = node->properties;
7968 while (attr != NULL) {
7969 if (attr->ns == NULL) {
7970 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7971 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007972 xmlSchemaPIllegalAttrErr(ctxt,
7973 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7974 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007975 }
7976 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007977 xmlSchemaPIllegalAttrErr(ctxt,
7978 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7979 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007980 }
7981 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007982 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007983
7984 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7985
William M. Brack2f2a6632004-08-20 23:09:47 +00007986 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7988 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007989 */
7990 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007991 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007992 /*
7993 * And now for the children...
7994 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007995 child = node->children;
7996 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007997 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7998 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007999 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008000 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008001 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008002 /*
8003 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008004 * Either the itemType [attribute] or the <simpleType> [child] of
8005 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008006 */
8007 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008008 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008009 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008010 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008011 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008012 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008013 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008014 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008015 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008016 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008017 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008018 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008019 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008020 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008021 "Either the attribute 'itemType' or the <simpleType> child "
8022 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008023 }
8024 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008025 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008026 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008027 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008028 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008029 if ((type->ref == NULL) &&
8030 (type->subtypes == NULL) &&
8031 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008032 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008033 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008034 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008035 "Either the attribute 'itemType' or the <simpleType> child "
8036 "must be present", NULL);
8037 }
8038 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008039}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008040
Daniel Veillard4255d502002-04-16 15:50:10 +00008041/**
8042 * xmlSchemaParseSimpleType:
8043 * @ctxt: a schema validation context
8044 * @schema: the schema being built
8045 * @node: a subtree containing XML Schema informations
8046 *
8047 * parse a XML schema Simple Type definition
8048 * *WARNING* this interface is highly subject to change
8049 *
William M. Bracke7091952004-05-11 15:09:58 +00008050 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008051 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008052 */
8053static xmlSchemaTypePtr
8054xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008055 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008056{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008057 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008058 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008059 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008060 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008061
8062 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8063 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008064
Daniel Veillardc0826a72004-08-10 14:17:33 +00008065 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008066 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008067 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008068 xmlSchemaPMissingAttrErr(ctxt,
8069 XML_SCHEMAP_S4S_ATTR_MISSING,
8070 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008071 "name", NULL);
8072 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008073 } else {
8074 if (xmlSchemaPValAttrNode(ctxt,
8075 NULL, NULL, attr,
8076 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8077 return (NULL);
8078 /*
8079 * Skip built-in types.
8080 */
8081 if (ctxt->isS4S) {
8082 xmlSchemaTypePtr biType;
8083
8084 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8085 if (biType != NULL)
8086 return (biType);
8087 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008088 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008089 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008090
Daniel Veillardc0826a72004-08-10 14:17:33 +00008091 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008092 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008093
Daniel Veillard01fa6152004-06-29 17:04:39 +00008094 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008095 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008096 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008097 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008098 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008099 if (type == NULL)
8100 return (NULL);
8101 type->node = node;
8102 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008103 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008104 /*
8105 * Check for illegal attributes.
8106 */
8107 attr = node->properties;
8108 while (attr != NULL) {
8109 if (attr->ns == NULL) {
8110 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008111 xmlSchemaPIllegalAttrErr(ctxt,
8112 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8113 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008114 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008115 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008116 xmlSchemaPIllegalAttrErr(ctxt,
8117 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8118 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008119 }
8120 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008121 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008122 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008123 /*
8124 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008125 *
8126 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008127 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008128 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008129 if (type == NULL)
8130 return (NULL);
8131 type->node = node;
8132 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008133 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008134 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8135 /*
8136 * Check for illegal attributes.
8137 */
8138 attr = node->properties;
8139 while (attr != NULL) {
8140 if (attr->ns == NULL) {
8141 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8142 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008143 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008144 xmlSchemaPIllegalAttrErr(ctxt,
8145 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8146 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008147 }
8148 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008149 xmlSchemaPIllegalAttrErr(ctxt,
8150 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8151 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008152 }
8153 attr = attr->next;
8154 }
8155 /*
8156 * Attribute "final".
8157 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008158 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008159 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008160 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8161 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8162 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8163 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8164 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8165 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008166 } else {
8167 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008168 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8169 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008170 XML_SCHEMAS_TYPE_FINAL_LIST,
8171 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8172
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008173 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008174 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008175 type, (xmlNodePtr) attr,
8176 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008177 attrValue, NULL, NULL, NULL);
8178 }
8179 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008180 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008181 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008182 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008183 /*
8184 * And now for the children...
8185 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008186 oldCtxtType = ctxt->ctxtType;
8187 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008188 ctxt->ctxtType = type;
8189 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008190 child = node->children;
8191 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008192 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8193 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008194 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008195 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008196 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8197 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008198 "(annotation?, (restriction | list | union))");
8199 } else if (IS_SCHEMA(child, "restriction")) {
8200 xmlSchemaParseRestriction(ctxt, schema, child,
8201 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008202 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008203 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008204 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008205 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008206 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008207 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008208 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008209 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008210 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008211 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8212 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008213 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008214 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008215 ctxt->parentItem = oldParentItem;
8216 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008217
Daniel Veillard4255d502002-04-16 15:50:10 +00008218 return (type);
8219}
8220
Daniel Veillard4255d502002-04-16 15:50:10 +00008221/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008222 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008223 * @ctxt: a schema validation context
8224 * @schema: the schema being built
8225 * @node: a subtree containing XML Schema informations
8226 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008227 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008228 * *WARNING* this interface is highly subject to change
8229 *
William M. Bracke7091952004-05-11 15:09:58 +00008230 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008231 * 1 in case of success.
8232 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008233static xmlSchemaTreeItemPtr
8234xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8235 xmlSchemaPtr schema,
8236 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008237{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008238 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008239 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008240 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008241 const xmlChar *ref = NULL, *refNs = NULL;
8242 int min, max;
8243
8244 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008245 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008246
8247 attr = xmlSchemaGetPropNode(node, "ref");
8248 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008249 xmlSchemaPMissingAttrErr(ctxt,
8250 XML_SCHEMAP_S4S_ATTR_MISSING,
8251 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008252 "ref", NULL);
8253 return (NULL);
8254 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008255 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008256 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008257 }
8258 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008259 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008260 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008261 /*
8262 * Check for illegal attributes.
8263 */
8264 attr = node->properties;
8265 while (attr != NULL) {
8266 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008267 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008268 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8269 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8270 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008271 xmlSchemaPIllegalAttrErr(ctxt,
8272 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8273 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008274 }
8275 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008276 xmlSchemaPIllegalAttrErr(ctxt,
8277 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8278 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008279 }
8280 attr = attr->next;
8281 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008282 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008283 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8284 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008285 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008286 /*
8287 * Create a reference item as the term; it will be substituted for
8288 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008289 */
8290 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008291 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8292 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8293 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8294 /*
8295 * And now for the children...
8296 */
8297 child = node->children;
8298 /* TODO: Is annotation even allowed for a model group reference? */
8299 if (IS_SCHEMA(child, "annotation")) {
8300 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008301 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008302 */
8303 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8304 child = child->next;
8305 }
8306 if (child != NULL) {
8307 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008308 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008309 NULL, NULL, node, child, NULL,
8310 "(annotation?)");
8311 }
8312 /*
8313 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8314 */
8315 if ((min == 0) && (max == 0))
8316 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008317 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008318 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8319 return ((xmlSchemaTreeItemPtr) item);
8320}
8321
8322/**
8323 * xmlSchemaParseModelGroupDefinition:
8324 * @ctxt: a schema validation context
8325 * @schema: the schema being built
8326 * @node: a subtree containing XML Schema informations
8327 *
8328 * Parses a XML schema model group definition.
8329 * *WARNING* this interface is highly subject to change
8330 *
8331 * Returns -1 in case of error, 0 if the declaration is improper and
8332 * 1 in case of success.
8333 */
8334static xmlSchemaModelGroupDefPtr
8335xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8336 xmlSchemaPtr schema,
8337 xmlNodePtr node)
8338{
8339 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008340 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008341 xmlAttrPtr attr;
8342 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008343
8344 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008345 return (NULL);
8346
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008347 attr = xmlSchemaGetPropNode(node, "name");
8348 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008349 xmlSchemaPMissingAttrErr(ctxt,
8350 XML_SCHEMAP_S4S_ATTR_MISSING,
8351 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008352 "name", NULL);
8353 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008354 } else if (xmlSchemaPValAttrNode(ctxt,
8355 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008356 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8357 return (NULL);
8358 }
8359 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8360 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008361 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008362 /*
8363 * Check for illegal attributes.
8364 */
8365 attr = node->properties;
8366 while (attr != NULL) {
8367 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008368 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008369 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008370 xmlSchemaPIllegalAttrErr(ctxt,
8371 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8372 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008373 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008374 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008375 xmlSchemaPIllegalAttrErr(ctxt,
8376 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8377 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008378 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008379 attr = attr->next;
8380 }
8381 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8382 /*
8383 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008384 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008385 child = node->children;
8386 if (IS_SCHEMA(child, "annotation")) {
8387 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8388 child = child->next;
8389 }
8390 if (IS_SCHEMA(child, "all")) {
8391 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8392 XML_SCHEMA_TYPE_ALL, 0);
8393 child = child->next;
8394 } else if (IS_SCHEMA(child, "choice")) {
8395 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8396 XML_SCHEMA_TYPE_CHOICE, 0);
8397 child = child->next;
8398 } else if (IS_SCHEMA(child, "sequence")) {
8399 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8400 XML_SCHEMA_TYPE_SEQUENCE, 0);
8401 child = child->next;
8402 }
8403 if (child != NULL) {
8404 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008405 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8406 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008407 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008408 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008409
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008410 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008411}
8412
8413/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008414 * xmlSchemaCleanupDoc:
8415 * @ctxt: a schema validation context
8416 * @node: the root of the document.
8417 *
8418 * removes unwanted nodes in a schemas document tree
8419 */
8420static void
8421xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8422{
8423 xmlNodePtr delete, cur;
8424
8425 if ((ctxt == NULL) || (root == NULL)) return;
8426
8427 /*
8428 * Remove all the blank text nodes
8429 */
8430 delete = NULL;
8431 cur = root;
8432 while (cur != NULL) {
8433 if (delete != NULL) {
8434 xmlUnlinkNode(delete);
8435 xmlFreeNode(delete);
8436 delete = NULL;
8437 }
8438 if (cur->type == XML_TEXT_NODE) {
8439 if (IS_BLANK_NODE(cur)) {
8440 if (xmlNodeGetSpacePreserve(cur) != 1) {
8441 delete = cur;
8442 }
8443 }
8444 } else if ((cur->type != XML_ELEMENT_NODE) &&
8445 (cur->type != XML_CDATA_SECTION_NODE)) {
8446 delete = cur;
8447 goto skip_children;
8448 }
8449
8450 /*
8451 * Skip to next node
8452 */
8453 if (cur->children != NULL) {
8454 if ((cur->children->type != XML_ENTITY_DECL) &&
8455 (cur->children->type != XML_ENTITY_REF_NODE) &&
8456 (cur->children->type != XML_ENTITY_NODE)) {
8457 cur = cur->children;
8458 continue;
8459 }
8460 }
8461 skip_children:
8462 if (cur->next != NULL) {
8463 cur = cur->next;
8464 continue;
8465 }
8466
8467 do {
8468 cur = cur->parent;
8469 if (cur == NULL)
8470 break;
8471 if (cur == root) {
8472 cur = NULL;
8473 break;
8474 }
8475 if (cur->next != NULL) {
8476 cur = cur->next;
8477 break;
8478 }
8479 } while (cur != NULL);
8480 }
8481 if (delete != NULL) {
8482 xmlUnlinkNode(delete);
8483 xmlFreeNode(delete);
8484 delete = NULL;
8485 }
8486}
8487
William M. Brack2f2a6632004-08-20 23:09:47 +00008488
8489/**
8490 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008491 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008492 * @ctxt: a schema validation context
8493 * @schemaLocation: an URI defining where to find the imported schema
8494 *
8495 * import a XML schema
8496 * *WARNING* this interface is highly subject to change
8497 *
8498 * Returns -1 in case of error and 1 in case of success.
8499 */
8500#if 0
8501static xmlSchemaImportPtr
8502xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8503 const xmlChar *schemaLocation)
8504{
8505 xmlSchemaImportPtr import;
8506 xmlSchemaParserCtxtPtr newctxt;
8507
8508 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8509 if (newctxt == NULL) {
8510 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8511 NULL);
8512 return (NULL);
8513 }
8514 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8515 /* Keep the same dictionnary for parsing, really */
8516 xmlDictReference(ctxt->dict);
8517 newctxt->dict = ctxt->dict;
8518 newctxt->includes = 0;
8519 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8520
8521 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8522 ctxt->userData);
8523
8524 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8525 if (import == NULL) {
8526 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8527 NULL);
8528 xmlSchemaFreeParserCtxt(newctxt);
8529 return (NULL);
8530 }
8531
8532 memset(import, 0, sizeof(xmlSchemaImport));
8533 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8534 import->schema = xmlSchemaParse(newctxt);
8535
8536 if (import->schema == NULL) {
8537 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008538 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008539 "Failed to import schema from location \"%s\".\n",
8540 schemaLocation, NULL);
8541
8542 xmlSchemaFreeParserCtxt(newctxt);
8543 /* The schemaLocation is held by the dictionary.
8544 if (import->schemaLocation != NULL)
8545 xmlFree((xmlChar *)import->schemaLocation);
8546 */
8547 xmlFree(import);
8548 return NULL;
8549 }
8550
8551 xmlSchemaFreeParserCtxt(newctxt);
8552 return import;
8553}
8554#endif
8555
8556static void
8557xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8558{
8559 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8560 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8561
8562 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8563 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8564
8565 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8566 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8567 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8568 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8569 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8570 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8571 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8572 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8573
8574 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8575 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8576 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8577 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8578 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8579 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8580}
8581
8582static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008583xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008584 xmlSchemaPtr schema,
8585 xmlNodePtr node)
8586{
8587 xmlAttrPtr attr;
8588 const xmlChar *val;
8589
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008590 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8591 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008592 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008593 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8594 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008595 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008596 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8597
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008598 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008599 if (attr != NULL) {
8600 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008601 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008602 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008604 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008606 "(qualified | unqualified)", val, NULL, NULL, NULL);
8607 }
8608 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008609
8610 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008611 if (attr != NULL) {
8612 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008613 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008614 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008615 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008616 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008617 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008618 "(qualified | unqualified)", val, NULL, NULL, NULL);
8619 }
8620 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008621
8622 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008623 if (attr != NULL) {
8624 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8625 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8626 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8627 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8628 -1,
8629 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8630 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8631 xmlSchemaPSimpleTypeErr(ctxt,
8632 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008633 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008634 "(#all | List of (extension | restriction | list | union))",
8635 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008636 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008637 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638
8639 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008640 if (attr != NULL) {
8641 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8642 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8643 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8644 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8645 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8646 xmlSchemaPSimpleTypeErr(ctxt,
8647 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008648 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008649 "(#all | List of (extension | restriction | substitution))",
8650 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008651 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008652 }
8653}
8654
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008655/**
8656 * xmlSchemaParseSchemaTopLevel:
8657 * @ctxt: a schema validation context
8658 * @schema: the schemas
8659 * @nodes: the list of top level nodes
8660 *
8661 * Returns the internal XML Schema structure built from the resource or
8662 * NULL in case of error
8663 */
8664static void
8665xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8666 xmlSchemaPtr schema, xmlNodePtr nodes)
8667{
8668 xmlNodePtr child;
8669 xmlSchemaAnnotPtr annot;
8670
8671 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8672 return;
8673
8674 child = nodes;
8675 while ((IS_SCHEMA(child, "include")) ||
8676 (IS_SCHEMA(child, "import")) ||
8677 (IS_SCHEMA(child, "redefine")) ||
8678 (IS_SCHEMA(child, "annotation"))) {
8679 if (IS_SCHEMA(child, "annotation")) {
8680 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8681 if (schema->annot == NULL)
8682 schema->annot = annot;
8683 else
8684 xmlSchemaFreeAnnot(annot);
8685 } else if (IS_SCHEMA(child, "import")) {
8686 xmlSchemaParseImport(ctxt, schema, child);
8687 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008688 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008689 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008690 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008691 } else if (IS_SCHEMA(child, "redefine")) {
Daniel Veillard77005e62005-07-19 16:26:18 +00008692 fprintf(stderr, "redefine is not yet implemented\n");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008693 TODO
8694 }
8695 child = child->next;
8696 }
8697 while (child != NULL) {
8698 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008699 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008700 child = child->next;
8701 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008702 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008703 child = child->next;
8704 } else if (IS_SCHEMA(child, "element")) {
8705 xmlSchemaParseElement(ctxt, schema, child, 1);
8706 child = child->next;
8707 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008708 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008709 child = child->next;
8710 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008711 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008712 child = child->next;
8713 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008714 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008715 child = child->next;
8716 } else if (IS_SCHEMA(child, "notation")) {
8717 xmlSchemaParseNotation(ctxt, schema, child);
8718 child = child->next;
8719 } else {
8720 xmlSchemaPErr2(ctxt, NULL, child,
8721 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008722 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008723 child->name, NULL);
8724 child = child->next;
8725 }
8726 while (IS_SCHEMA(child, "annotation")) {
8727 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8728 if (schema->annot == NULL)
8729 schema->annot = annot;
8730 else
8731 xmlSchemaFreeAnnot(annot);
8732 child = child->next;
8733 }
8734 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008735 ctxt->parentItem = NULL;
8736 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008737}
8738
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008739static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008740xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008741 xmlHashTablePtr *imports,
8742 const xmlChar *nsName)
8743{
8744 xmlSchemaImportPtr ret;
8745
8746 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008747 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008748 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008749 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008750 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8751 NULL, NULL, (xmlNodePtr) ctxt->doc,
8752 "Internal error: failed to build the import table",
8753 NULL);
8754 return (NULL);
8755 }
8756 }
8757 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8758 if (ret == NULL) {
8759 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8760 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008761 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008762 memset(ret, 0, sizeof(xmlSchemaImport));
8763 if (nsName == NULL)
8764 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008765 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008766
8767 return (ret);
8768}
8769
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008770/**
8771 * xmlSchemaNewParserCtxtUseDict:
8772 * @URL: the location of the schema
8773 * @dict: the dictionary to be used
8774 *
8775 * Create an XML Schemas parse context for that file/resource expected
8776 * to contain an XML Schemas file.
8777 *
8778 * Returns the parser context or NULL in case of error
8779 */
8780static xmlSchemaParserCtxtPtr
8781xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8782{
8783 xmlSchemaParserCtxtPtr ret;
8784 /*
8785 if (URL == NULL)
8786 return (NULL);
8787 */
8788
8789 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8790 if (ret == NULL) {
8791 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8792 NULL);
8793 return (NULL);
8794 }
8795 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8796 ret->dict = dict;
8797 xmlDictReference(dict);
8798 if (URL != NULL)
8799 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8800 ret->includes = 0;
8801 return (ret);
8802}
8803
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008804static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008805xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8806{
8807 if (vctxt->pctxt == NULL) {
8808 if (vctxt->schema != NULL)
8809 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8810 else
8811 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8812 if (vctxt->pctxt == NULL) {
8813 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8814 "failed to create a temp. parser context");
8815 return (-1);
8816 }
8817 /* TODO: Pass user data. */
8818 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8819 }
8820 return (0);
8821}
8822
8823static int
8824xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008825 xmlSchemaPtr schema,
8826 xmlNodePtr node,
8827 const xmlChar *nsName,
8828 const xmlChar *location,
8829 xmlDocPtr *doc,
8830 const xmlChar **targetNamespace,
8831 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008832{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008833 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008834 xmlParserCtxtPtr parserCtxt;
8835 xmlSchemaImportPtr import;
8836 const xmlChar *ns;
8837 xmlNodePtr root;
8838
8839 /*
8840 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8841 * <xsi:noNamespaceSchemaLocation>.
8842 */
8843 *doc = NULL;
8844 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008845 * Given that the schemaLocation [attribute] is only a hint, it is open
8846 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008847 * namespace, regardless of the ·actual value· of schemaLocation, but
8848 * such a strategy risks missing useful information when new
8849 * schemaLocations are offered.
8850 *
8851 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8852 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8853 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008854 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008855 */
8856 if (location == NULL) {
8857 /*
8858 * Schema Document Location Strategy:
8859 *
8860 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008861 * either as a resource which is an XML document or a <schema> element
8862 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008863 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008864 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008865 *
8866 * NOTE: Those stategies are not supported, so we will skip.
8867 */
8868 return (0);
8869 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008870 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008871 ns = XML_SCHEMAS_NO_NAMESPACE;
8872 else
8873 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008874
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008875 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008876 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008877 /*
8878 * There was a valid resource for the specified namespace already
8879 * defined, so skip.
8880 * TODO: This might be changed someday to allow import of
8881 * components from multiple documents for a single target namespace.
8882 */
8883 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008884 }
8885 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8886 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8887 else {
8888 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8889 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8890 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008891 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008892 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008893 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008894 * 2 Based on the location URI, identify an existing schema document,
8895 * either as a resource which is an XML document or a <schema> element
8896 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008897 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008898 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008899 * web which is or contains or references a <schema> element;
8900 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8901 *
8902 */
8903 if ((absolute == 0) && (node != NULL)) {
8904 xmlChar *base, *URI;
8905
8906 base = xmlNodeGetBase(node->doc, node);
8907 if (base == NULL) {
8908 URI = xmlBuildURI(location, node->doc->URL);
8909 } else {
8910 URI = xmlBuildURI(location, base);
8911 xmlFree(base);
8912 }
8913 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008914 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008915 xmlFree(URI);
8916 }
8917 }
8918 parserCtxt = xmlNewParserCtxt();
8919 if (parserCtxt == NULL) {
8920 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8921 "allocating a parser context", NULL);
8922 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008923 }
8924 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008925 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008926 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008927 xmlDictReference(parserCtxt->dict);
8928 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008929 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008930 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008931 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008932 * 2.1 The referent is (a fragment of) a resource which is an
8933 * XML document (see clause 1.1), which in turn corresponds to
8934 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008935 * set, which in turn corresponds to a valid schema.
8936 * TODO: What to do with the "fragment" stuff?
8937 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008938 * 2.2 The referent is a <schema> element information item in
8939 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008940 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008941 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008942 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008943 */
8944 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008945 xmlErrorPtr lerr;
8946 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008947 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008948 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008949 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008950 * If the doc is NULL and the parser error is an IO error we
8951 * will assume that the resource could not be located or accessed.
8952 *
8953 * TODO: Try to find specific error codes to react only on
8954 * localisation failures.
8955 *
8956 * TODO, FIXME: Check the spec: is a namespace added to the imported
8957 * namespaces, even if the schemaLocation did not provide
8958 * a resource? I guess so, since omitting the "schemaLocation"
8959 * attribute, imports a namespace as well.
8960 */
8961 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008962 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008963 xmlFreeParserCtxt(parserCtxt);
8964 return(0);
8965 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008966 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008967 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008968 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008969 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008970 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008971 xmlFreeParserCtxt(parserCtxt);
8972 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8973 }
8974 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008975
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008976 root = xmlDocGetRootElement(*doc);
8977 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008978 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008979 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008980 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008981 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008982 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008983 xmlFreeDoc(*doc);
8984 *doc = NULL;
8985 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008986 }
8987
8988 xmlSchemaCleanupDoc(pctxt, root);
8989
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008990 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008991 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008992 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008993 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008994 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008995 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008996 xmlFreeDoc(*doc);
8997 *doc = NULL;
8998 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008999 }
9000 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009001 /*
9002 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009003 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009004 if (nsName == NULL) {
9005 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009006 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009007 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009008 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009009 "The XML schema to be imported is not expected "
9010 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009011 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009012 xmlFreeDoc(*doc);
9013 *doc = NULL;
9014 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9015 }
9016 } else {
9017 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009018 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009019 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009020 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009021 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009022 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009023 xmlFreeDoc(*doc);
9024 *doc = NULL;
9025 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9026 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009027 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009028 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009029 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009030 "The XML schema to be imported is expected to have a "
9031 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009032 "its target namespace of '%s'",
9033 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009034 xmlFreeDoc(*doc);
9035 *doc = NULL;
9036 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9037 }
9038 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009039 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009040 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009041 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9042 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009043 xmlFreeDoc(*doc);
9044 *doc = NULL;
9045 return (-1);
9046 }
9047 import->schemaLocation = location;
9048 import->doc = *doc;
9049 return (0);
9050}
William M. Brack2f2a6632004-08-20 23:09:47 +00009051
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009052static void
9053xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9054 xmlSchemaPtr schema,
9055 const xmlChar *targetNamespace,
9056 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009057{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009058 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009059 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009060
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009061 /*
9062 * Save and reset the context & schema.
9063 */
9064 oldURL = pctxt->URL;
9065 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009066 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009067 oldLocImps = pctxt->localImports;
9068 pctxt->localImports = NULL;
9069 oldNumLocImps = pctxt->nbLocalImports;
9070 pctxt->nbLocalImports = 0;
9071 oldSizeLocImps = pctxt->sizeLocalImports;
9072 pctxt->sizeLocalImports = 0;
9073 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009074 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009075 xmlSchemaClearSchemaDefaults(schema);
9076 oldTNS = schema->targetNamespace;
9077 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009078 if ((targetNamespace != NULL) &&
9079 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9080 /*
9081 * We are parsing the schema for schema!
9082 */
9083 pctxt->isS4S = 1;
9084 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009085 /*
9086 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009087 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009088 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9089 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9090 /*
9091 * Restore the context & schema.
9092 */
9093 schema->flags = oldFlags;
9094 schema->targetNamespace = oldTNS;
9095 if (pctxt->localImports != NULL)
9096 xmlFree((xmlChar *) pctxt->localImports);
9097 pctxt->localImports = oldLocImps;
9098 pctxt->nbLocalImports = oldNumLocImps;
9099 pctxt->sizeLocalImports = oldSizeLocImps;
9100 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009101 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009102}
9103
William M. Brack2f2a6632004-08-20 23:09:47 +00009104/**
9105 * xmlSchemaParseImport:
9106 * @ctxt: a schema validation context
9107 * @schema: the schema being built
9108 * @node: a subtree containing XML Schema informations
9109 *
9110 * parse a XML schema Import definition
9111 * *WARNING* this interface is highly subject to change
9112 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009113 * Returns 0 in case of success, a positive error code if
9114 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009115 */
9116static int
9117xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9118 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009119{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009120 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009121 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009122 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009123 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009124 xmlAttrPtr attr;
9125 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009126 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009127
9128 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9129 return (-1);
9130
9131 /*
9132 * Check for illegal attributes.
9133 */
9134 attr = node->properties;
9135 while (attr != NULL) {
9136 if (attr->ns == NULL) {
9137 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9138 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9139 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009140 xmlSchemaPIllegalAttrErr(ctxt,
9141 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9142 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009143 }
9144 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009145 xmlSchemaPIllegalAttrErr(ctxt,
9146 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9147 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009148 }
9149 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009150 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009151 /*
9152 * Extract and validate attributes.
9153 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009154 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9155 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009156 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009157 xmlSchemaPSimpleTypeErr(ctxt,
9158 XML_SCHEMAP_IMPORT_NAMESPACE_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_NAMESPACE_NOT_URI);
9163 }
9164
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009165 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9166 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009167 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009168 xmlSchemaPSimpleTypeErr(ctxt,
9169 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9170 NULL, node,
9171 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009172 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009173 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009174 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009175 /*
9176 * And now for the children...
9177 */
9178 child = node->children;
9179 if (IS_SCHEMA(child, "annotation")) {
9180 /*
9181 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009182 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009183 */
9184 child = child->next;
9185 }
9186 if (child != NULL) {
9187 xmlSchemaPContentErr(ctxt,
9188 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9189 NULL, NULL, node, child, NULL,
9190 "(annotation?)");
9191 }
9192 /*
9193 * Apply additional constraints.
9194 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009195 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009196 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009197 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9198 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009199 * targetNamespace [attribute].
9200 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009201 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009202 xmlSchemaPCustomErr(ctxt,
9203 XML_SCHEMAP_SRC_IMPORT_1_1,
9204 NULL, NULL, node,
9205 "The value of the attribute 'namespace' must not match "
9206 "the target namespace '%s' of the importing schema",
9207 schema->targetNamespace);
9208 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9209 }
9210 } else {
9211 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009212 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009213 * <schema> must have a targetNamespace [attribute].
9214 */
9215 if (schema->targetNamespace == NULL) {
9216 xmlSchemaPCustomErr(ctxt,
9217 XML_SCHEMAP_SRC_IMPORT_1_2,
9218 NULL, NULL, node,
9219 "The attribute 'namespace' must be existent if "
9220 "the importing schema has no target namespace",
9221 NULL);
9222 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9223 }
9224 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009225 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009226 * Add the namespace to the list of locally imported namespace.
9227 */
9228 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009229 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009230 sizeof(const xmlChar*));
9231 ctxt->sizeLocalImports = 10;
9232 ctxt->nbLocalImports = 0;
9233 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9234 ctxt->sizeLocalImports *= 2;
9235 ctxt->localImports = (const xmlChar **) xmlRealloc(
9236 (xmlChar **) ctxt->localImports,
9237 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9238 }
9239 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9240 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009241 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009242 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009243 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9244 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009245 schemaLocation, &doc, &targetNamespace, 0);
9246 if (ret != 0) {
9247 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009248 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009249 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009250 } else if (doc != NULL) {
9251 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9252 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009253 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009254
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009255 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009256}
9257
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009258/**
9259 * xmlSchemaParseInclude:
9260 * @ctxt: a schema validation context
9261 * @schema: the schema being built
9262 * @node: a subtree containing XML Schema informations
9263 *
9264 * parse a XML schema Include definition
9265 *
William M. Bracke7091952004-05-11 15:09:58 +00009266 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009267 * 1 in case of success.
9268 */
9269static int
9270xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9271 xmlNodePtr node)
9272{
9273 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009274 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009275 xmlDocPtr doc = NULL;
9276 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009277 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009278 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009279 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009280 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009281
9282
9283 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9284 return (-1);
9285
9286 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009287 * Check for illegal attributes.
9288 */
9289 attr = node->properties;
9290 while (attr != NULL) {
9291 if (attr->ns == NULL) {
9292 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9293 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009294 xmlSchemaPIllegalAttrErr(ctxt,
9295 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9296 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009297 }
9298 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009299 xmlSchemaPIllegalAttrErr(ctxt,
9300 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9301 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009302 }
9303 attr = attr->next;
9304 }
9305 /*
9306 * Extract and validate attributes.
9307 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009308 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009309 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009310 * Preliminary step, extract the URI-Reference for the include and
9311 * make an URI from the base.
9312 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009313 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9314 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009315 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009316 xmlChar *uri = NULL;
9317
9318 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9319 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009320 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009321 base = xmlNodeGetBase(node->doc, node);
9322 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009323 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009324 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009325 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009326 xmlFree(base);
9327 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009328 if (uri == NULL) {
9329 xmlSchemaPErr(ctxt,
9330 node,
9331 XML_SCHEMAP_INTERNAL,
9332 "Internal error: xmlSchemaParseInclude, "
9333 "could not build an URI from the schemaLocation.\n",
9334 NULL, NULL);
9335 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009336 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009337 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9338 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009339 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009340 xmlSchemaPMissingAttrErr(ctxt,
9341 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9342 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009343 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009344 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009345 /*
9346 * And now for the children...
9347 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009348 child = node->children;
9349 while (IS_SCHEMA(child, "annotation")) {
9350 /*
9351 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009352 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009353 */
9354 child = child->next;
9355 }
9356 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009357 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009358 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9359 NULL, NULL, node, child, NULL,
9360 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009361 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009362 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009363 * Report self-inclusion.
9364 */
9365 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9366 xmlSchemaPCustomErr(ctxt,
9367 XML_SCHEMAP_SRC_INCLUDE,
9368 NULL, NULL, node,
9369 "The schema document '%s' cannot include itself.",
9370 schemaLocation);
9371 return (XML_SCHEMAP_SRC_INCLUDE);
9372 }
9373 /*
9374 * Check if this one was already processed to avoid incorrect
9375 * duplicate component errors and infinite circular inclusion.
9376 */
9377 include = schema->includes;
9378 while (include != NULL) {
9379 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9380 targetNamespace = include->origTargetNamespace;
9381 if (targetNamespace == NULL) {
9382 /*
9383 * Chameleon include: skip only if it was build for
9384 * the targetNamespace of the including schema.
9385 */
9386 if (xmlStrEqual(schema->targetNamespace,
9387 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009388 goto check_targetNamespace;
9389 }
9390 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009391 goto check_targetNamespace;
9392 }
9393 }
9394 include = include->next;
9395 }
9396 /*
9397 * First step is to parse the input document into an DOM/Infoset
9398 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009399 */
9400 parserCtxt = xmlNewParserCtxt();
9401 if (parserCtxt == NULL) {
9402 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9403 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009404 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009405 }
9406
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009407 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9408 xmlDictFree(parserCtxt->dict);
9409 parserCtxt->dict = ctxt->dict;
9410 xmlDictReference(parserCtxt->dict);
9411 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009412
9413 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009414 NULL, SCHEMAS_PARSE_OPTIONS);
9415 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009416 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009417 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009418 * TODO: It is not an error for the ·actual value· of the
9419 * schemaLocation [attribute] to fail to resolve it all, in which
9420 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009421 * So do we need a warning report here?
9422 */
9423 xmlSchemaPCustomErr(ctxt,
9424 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009425 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009426 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009427 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009428 }
9429
9430 /*
9431 * Then extract the root of the schema
9432 */
9433 root = xmlDocGetRootElement(doc);
9434 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009435 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009436 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009437 NULL, NULL, node,
9438 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009439 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009440 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009441 }
9442
9443 /*
9444 * Remove all the blank text nodes
9445 */
9446 xmlSchemaCleanupDoc(ctxt, root);
9447
9448 /*
9449 * Check the schemas top level element
9450 */
9451 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009452 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009453 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009454 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009455 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009456 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009457 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009458 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009459
William M. Brack2f2a6632004-08-20 23:09:47 +00009460 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009461 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009462 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9463 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009464 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9465 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009466check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009467 if (targetNamespace != NULL) {
9468 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009469 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009470 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009471 NULL, NULL, node,
9472 "The target namespace of the included schema "
9473 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009474 "has no target namespace",
9475 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009476 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009477 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9478 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009479 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009480 NULL, NULL, node,
9481 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009482 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009483 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009484 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009485 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009486 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009487 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009488 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009489 } else
9490 wasConvertingNs = 1;
9491 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009492
9493 if (include != NULL)
9494 goto exit;
9495
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009496 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009497 * URGENT TODO: If the schema is a chameleon-include then copy the
9498 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009499 * of those components, do nothing otherwise.
9500 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009501 * for every destinct including targetNamespace; thus not performant at
9502 * the moment.
9503 * TODO: Check when the namespace in wildcards for chameleons needs
9504 * to be converted: before we built wildcard intersections or after.
9505 */
9506 /*
9507 * Register the include.
9508 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009509 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9510 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009511 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9512 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009513 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009514 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009515 include->next = schema->includes;
9516 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009517 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009518 * TODO: Use the resolved URI for the this location, since it might
9519 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009520 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009521 include->schemaLocation = schemaLocation;
9522 include->doc = doc;
9523 /*
9524 * In case of chameleons, the original target namespace will differ
9525 * from the resulting namespace.
9526 */
9527 include->origTargetNamespace = targetNamespace;
9528 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009529#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009530 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009531 xmlGenericError(xmlGenericErrorContext,
9532 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9533 " into TNS '%s'\n", schemaLocation,
9534 targetNamespace, schema->targetNamespace);
9535 else
9536 xmlGenericError(xmlGenericErrorContext,
9537 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9538 targetNamespace);
9539#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009540 /*
9541 * Compile the included schema.
9542 */
9543 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9544
9545exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009546 /*
9547 * Remove the converting flag.
9548 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009549 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009550 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009551 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009552 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009553
9554exit_invalid:
9555 if (doc != NULL) {
9556 if (include != NULL)
9557 include->doc = NULL;
9558 xmlFreeDoc(doc);
9559 }
9560 return (ctxt->err);
9561
9562exit_failure:
9563 if (doc != NULL) {
9564 if (include != NULL)
9565 include->doc = NULL;
9566 xmlFreeDoc(doc);
9567 }
9568 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009569}
9570
9571/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009572 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009573 * @ctxt: a schema validation context
9574 * @schema: the schema being built
9575 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009576 * @type: the "compositor" type
9577 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009578 *
9579 * parse a XML schema Sequence definition
9580 * *WARNING* this interface is highly subject to change
9581 *
William M. Bracke7091952004-05-11 15:09:58 +00009582 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009583 * 1 in case of success.
9584 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009585static xmlSchemaTreeItemPtr
9586xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9587 xmlNodePtr node, xmlSchemaTypeType type,
9588 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009589{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009590 xmlSchemaModelGroupPtr item;
9591 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009592 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009593 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009594 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009595 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009596
9597 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009598 return (NULL);
9599 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009600 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009601 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009602 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9603 if (item == NULL)
9604 return (NULL);
9605
9606 if (withParticle) {
9607 if (type == XML_SCHEMA_TYPE_ALL) {
9608 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009609 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009610 } else {
9611 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009612 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9613 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9614 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009615 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009616 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9617 /*
9618 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009619 */
9620 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9621 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009622 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009623 particle->children = (xmlSchemaTreeItemPtr) item;
9624 /*
9625 * Check for illegal attributes.
9626 */
9627 attr = node->properties;
9628 while (attr != NULL) {
9629 if (attr->ns == NULL) {
9630 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9631 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9632 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009633 xmlSchemaPIllegalAttrErr(ctxt,
9634 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9635 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009636 }
9637 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009638 xmlSchemaPIllegalAttrErr(ctxt,
9639 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9640 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009641 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009642 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009643 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009644 } else {
9645 /*
9646 * Check for illegal attributes.
9647 */
9648 attr = node->properties;
9649 while (attr != NULL) {
9650 if (attr->ns == NULL) {
9651 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009652 xmlSchemaPIllegalAttrErr(ctxt,
9653 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9654 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009655 }
9656 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009657 xmlSchemaPIllegalAttrErr(ctxt,
9658 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9659 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009660 }
9661 attr = attr->next;
9662 }
9663
William M. Brack2f2a6632004-08-20 23:09:47 +00009664 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009665
William M. Brack2f2a6632004-08-20 23:09:47 +00009666 /*
9667 * Extract and validate attributes.
9668 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009669 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009670 /*
9671 * And now for the children...
9672 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009673 child = node->children;
9674 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009675 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009676 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009677 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009678 oldcontainer = ctxt->container;
9679 ctxt->container = container;
9680 if (type == XML_SCHEMA_TYPE_ALL) {
9681 xmlSchemaParticlePtr part, last = NULL;
9682
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009683 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009684 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9685 schema, child, 0);
9686 if (part != NULL) {
9687 if (part->minOccurs > 1)
9688 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009689 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009690 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9691 if (part->maxOccurs > 1)
9692 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009693 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009694 "Invalid value for maxOccurs (must be 0 or 1)",
9695 NULL);
9696 if (last == NULL)
9697 item->children = (xmlSchemaTreeItemPtr) part;
9698 else
9699 last->next = (xmlSchemaTreeItemPtr) part;
9700 last = part;
9701 }
9702 child = child->next;
9703 }
9704 if (child != NULL) {
9705 xmlSchemaPContentErr(ctxt,
9706 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9707 NULL, NULL, node, child, NULL,
9708 "(annotation?, (annotation?, element*)");
9709 }
9710 } else {
9711 /* choice + sequence */
9712 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9713
9714 while ((IS_SCHEMA(child, "element")) ||
9715 (IS_SCHEMA(child, "group")) ||
9716 (IS_SCHEMA(child, "any")) ||
9717 (IS_SCHEMA(child, "choice")) ||
9718 (IS_SCHEMA(child, "sequence"))) {
9719
9720 if (IS_SCHEMA(child, "element")) {
9721 part = (xmlSchemaTreeItemPtr)
9722 xmlSchemaParseElement(ctxt, schema, child, 0);
9723 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009724 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009725 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9726 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009727 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009728 xmlSchemaParseAny(ctxt, schema, child);
9729 } else if (IS_SCHEMA(child, "choice")) {
9730 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9731 XML_SCHEMA_TYPE_CHOICE, 1);
9732 } else if (IS_SCHEMA(child, "sequence")) {
9733 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9734 XML_SCHEMA_TYPE_SEQUENCE, 1);
9735 }
9736 if (part != NULL) {
9737 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009738 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009739 else
9740 last->next = part;
9741 last = part;
9742 }
9743 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009744 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009745 if (child != NULL) {
9746 xmlSchemaPContentErr(ctxt,
9747 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9748 NULL, NULL, node, child, NULL,
9749 "(annotation?, (element | group | choice | sequence | any)*)");
9750 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009751 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009752 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009753 if (withParticle) {
9754 if ((min == 0) && (max == 0))
9755 return (NULL);
9756 else
9757 return ((xmlSchemaTreeItemPtr) particle);
9758 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009759 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009760}
9761
9762/**
9763 * xmlSchemaParseRestriction:
9764 * @ctxt: a schema validation context
9765 * @schema: the schema being built
9766 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009767 *
9768 * parse a XML schema Restriction definition
9769 * *WARNING* this interface is highly subject to change
9770 *
9771 * Returns the type definition or NULL in case of error
9772 */
9773static xmlSchemaTypePtr
9774xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009775 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009776{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009777 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009778 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009779 char buf[30];
9780 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009781 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009782
9783 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9784 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009785 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009786 type = ctxt->ctxtType;
9787 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009788
9789 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009790 * TODO: Is the container needed at all? the anonymous
9791 * items inside should generate unique names already.
9792 */
9793 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009794 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009795 /*
9796 * Check for illegal attributes.
9797 */
9798 attr = node->properties;
9799 while (attr != NULL) {
9800 if (attr->ns == NULL) {
9801 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9802 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009803 xmlSchemaPIllegalAttrErr(ctxt,
9804 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9805 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009806 }
9807 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009808 xmlSchemaPIllegalAttrErr(ctxt,
9809 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9810 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009811 }
9812 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009813 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009814 /*
9815 * Extract and validate attributes.
9816 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009817 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009818 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009819 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009820 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009821 /*
9822 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9823 * among its [children]), the simple type definition which is
9824 * the {content type} of the type definition ·resolved· to by
9825 * the ·actual value· of the base [attribute]"
9826 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009827 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009828 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009829 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009830 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009831 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009832 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009833 XML_SCHEMAP_S4S_ATTR_MISSING,
9834 type, node, "base", NULL);
9835 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009836 /*
9837 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009838 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009839 child = node->children;
9840 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009841 /*
9842 * Add the annotation to the simple type ancestor.
9843 */
9844 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9845 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009846 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009847 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009848 oldcontainer = ctxt->container;
9849 ctxt->container = container;
9850 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9851 /*
9852 * Corresponds to <simpleType><restriction><simpleType>.
9853 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009854 if (IS_SCHEMA(child, "simpleType")) {
9855 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009856 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009857 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009858 * Either the base [attribute] or the simpleType [child] of the
9859 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009860 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009861 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009862 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009863 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009864 "The attribute 'base' and the <simpleType> child are "
9865 "mutually exclusive", NULL);
9866 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009867 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009868 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009869 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009870 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009871 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009872 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009873 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9874 NULL, NULL, node, child,
9875 "Either the attribute 'base' or a <simpleType> child "
9876 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009877 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009878 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9879 /*
9880 * Corresponds to <complexType><complexContent><restriction>...
9881 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009882 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009883 * Model groups <all>, <choice> and <sequence>.
9884 */
9885 if (IS_SCHEMA(child, "all")) {
9886 type->subtypes = (xmlSchemaTypePtr)
9887 xmlSchemaParseModelGroup(ctxt, schema, child,
9888 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009889 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009890 } else if (IS_SCHEMA(child, "choice")) {
9891 type->subtypes = (xmlSchemaTypePtr)
9892 xmlSchemaParseModelGroup(ctxt,
9893 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9894 child = child->next;
9895 } else if (IS_SCHEMA(child, "sequence")) {
9896 type->subtypes = (xmlSchemaTypePtr)
9897 xmlSchemaParseModelGroup(ctxt, schema, child,
9898 XML_SCHEMA_TYPE_SEQUENCE, 1);
9899 child = child->next;
9900 /*
9901 * Model group reference <group>.
9902 */
9903 } else if (IS_SCHEMA(child, "group")) {
9904 type->subtypes = (xmlSchemaTypePtr)
9905 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9906 child = child->next;
9907 }
9908 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009909 /*
9910 * Corresponds to <complexType><simpleContent><restriction>...
9911 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009912 * "1.1 the simple type definition corresponding to the <simpleType>
9913 * among the [children] of <restriction> if there is one;"
9914 */
9915 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009916 /*
9917 * We will store the to-be-restricted simple type in
9918 * type->contentTypeDef *temporarily*.
9919 */
9920 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009921 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009922 if ( type->contentTypeDef == NULL)
9923 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009924 child = child->next;
9925 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009926 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009927
9928 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009929 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009930 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009931 /*
9932 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009933 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009934 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009935
Daniel Veillard01fa6152004-06-29 17:04:39 +00009936 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009937 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009938 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009939 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009940 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9941 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009942 * *Single Facet Value*
9943 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009944 while ((IS_SCHEMA(child, "minInclusive")) ||
9945 (IS_SCHEMA(child, "minExclusive")) ||
9946 (IS_SCHEMA(child, "maxInclusive")) ||
9947 (IS_SCHEMA(child, "maxExclusive")) ||
9948 (IS_SCHEMA(child, "totalDigits")) ||
9949 (IS_SCHEMA(child, "fractionDigits")) ||
9950 (IS_SCHEMA(child, "pattern")) ||
9951 (IS_SCHEMA(child, "enumeration")) ||
9952 (IS_SCHEMA(child, "whiteSpace")) ||
9953 (IS_SCHEMA(child, "length")) ||
9954 (IS_SCHEMA(child, "maxLength")) ||
9955 (IS_SCHEMA(child, "minLength"))) {
9956 facet = xmlSchemaParseFacet(ctxt, schema, child);
9957 if (facet != NULL) {
9958 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009959 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009960 else
9961 lastfacet->next = facet;
9962 lastfacet = facet;
9963 lastfacet->next = NULL;
9964 }
9965 child = child->next;
9966 }
9967 /*
9968 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009969 */
9970 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009971 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9972
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009973 facet = type->facets;
9974 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009975 facetLink = (xmlSchemaFacetLinkPtr)
9976 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009977 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009978 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009979 xmlFree(facetLink);
9980 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009981 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009982 facetLink->facet = facet;
9983 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009984 if (lastFacetLink == NULL)
9985 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009986 else
9987 lastFacetLink->next = facetLink;
9988 lastFacetLink = facetLink;
9989 facet = facet->next;
9990 } while (facet != NULL);
9991 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009992 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009993 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9994 /*
9995 * Attribute uses/declarations.
9996 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009997 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009998 /*
9999 * Attribute wildcard.
10000 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010001 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010002 type->attributeWildcard =
10003 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010004 child = child->next;
10005 }
10006 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010007 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010008 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10009 xmlSchemaPContentErr(ctxt,
10010 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010011 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010012 "annotation?, (group | all | choice | sequence)?, "
10013 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010014 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010015 xmlSchemaPContentErr(ctxt,
10016 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010017 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010018 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10019 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10020 "length | minLength | maxLength | enumeration | whiteSpace | "
10021 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10022 } else {
10023 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010024 xmlSchemaPContentErr(ctxt,
10025 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010026 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010027 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10028 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10029 "length | minLength | maxLength | enumeration | whiteSpace | "
10030 "pattern)*))");
10031 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010032 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010033 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010034 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010035}
10036
10037/**
10038 * xmlSchemaParseExtension:
10039 * @ctxt: a schema validation context
10040 * @schema: the schema being built
10041 * @node: a subtree containing XML Schema informations
10042 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010043 * Parses an <extension>, which is found inside a
10044 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010045 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010046 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010047 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010048 */
10049static xmlSchemaTypePtr
10050xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010051 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010052{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010053 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010054 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010055 char buf[30];
10056 const xmlChar *oldcontainer, *container;
10057 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010058
10059 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10060 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010061 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010062 type = ctxt->ctxtType;
10063 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010064
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010065 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10066 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10067 /*
10068 * Check for illegal attributes.
10069 */
10070 attr = node->properties;
10071 while (attr != NULL) {
10072 if (attr->ns == NULL) {
10073 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10074 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010075 xmlSchemaPIllegalAttrErr(ctxt,
10076 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10077 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010078 }
10079 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010080 xmlSchemaPIllegalAttrErr(ctxt,
10081 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10082 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010083 }
10084 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010085 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010086
10087 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010088
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010089 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010090 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010091 */
10092 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010093 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10094 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010095 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010096 XML_SCHEMAP_S4S_ATTR_MISSING,
10097 NULL, node, "base", NULL);
10098 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010099 /*
10100 * And now for the children...
10101 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010102 child = node->children;
10103 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010104 /*
10105 * Add the annotation to the type ancestor.
10106 */
10107 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10108 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010109 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010110 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010111 oldcontainer = ctxt->container;
10112 ctxt->container = container;
10113 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10114 /*
10115 * Corresponds to <complexType><complexContent><extension>... and:
10116 *
10117 * Model groups <all>, <choice>, <sequence> and <group>.
10118 */
10119 if (IS_SCHEMA(child, "all")) {
10120 type->subtypes = (xmlSchemaTypePtr)
10121 xmlSchemaParseModelGroup(ctxt, schema,
10122 child, XML_SCHEMA_TYPE_ALL, 1);
10123 child = child->next;
10124 } else if (IS_SCHEMA(child, "choice")) {
10125 type->subtypes = (xmlSchemaTypePtr)
10126 xmlSchemaParseModelGroup(ctxt, schema,
10127 child, XML_SCHEMA_TYPE_CHOICE, 1);
10128 child = child->next;
10129 } else if (IS_SCHEMA(child, "sequence")) {
10130 type->subtypes = (xmlSchemaTypePtr)
10131 xmlSchemaParseModelGroup(ctxt, schema,
10132 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10133 child = child->next;
10134 } else if (IS_SCHEMA(child, "group")) {
10135 type->subtypes = (xmlSchemaTypePtr)
10136 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10137 child = child->next;
10138 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010139 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010140 if (child != NULL) {
10141 /*
10142 * Attribute uses/declarations.
10143 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010144 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010145 /*
10146 * Attribute wildcard.
10147 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010148 if (IS_SCHEMA(child, "anyAttribute")) {
10149 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010150 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10151 child = child->next;
10152 }
10153 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010154 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010155 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10156 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010157 xmlSchemaPContentErr(ctxt,
10158 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010159 NULL, NULL, node, child, NULL,
10160 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010161 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010162 } else {
10163 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010164 xmlSchemaPContentErr(ctxt,
10165 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010166 NULL, NULL, node, child, NULL,
10167 "(annotation?, ((attribute | attributeGroup)*, "
10168 "anyAttribute?))");
10169 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010170 }
10171 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010172 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010173}
10174
10175/**
10176 * xmlSchemaParseSimpleContent:
10177 * @ctxt: a schema validation context
10178 * @schema: the schema being built
10179 * @node: a subtree containing XML Schema informations
10180 *
10181 * parse a XML schema SimpleContent definition
10182 * *WARNING* this interface is highly subject to change
10183 *
10184 * Returns the type definition or NULL in case of error
10185 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010186static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010187xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10188 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010189{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010190 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010191 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010192 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010193
10194 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010195 return (-1);
10196 /* Not a component, don't create it. */
10197 type = ctxt->ctxtType;
10198 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10199 /*
10200 * Check for illegal attributes.
10201 */
10202 attr = node->properties;
10203 while (attr != NULL) {
10204 if (attr->ns == NULL) {
10205 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010206 xmlSchemaPIllegalAttrErr(ctxt,
10207 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10208 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010209 }
10210 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010211 xmlSchemaPIllegalAttrErr(ctxt,
10212 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10213 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010214 }
10215 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010216 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010217
10218 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010219
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010220 /*
10221 * And now for the children...
10222 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010223 child = node->children;
10224 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010225 /*
10226 * Add the annotation to the complex type ancestor.
10227 */
10228 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10229 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010230 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010231 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010232 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010233 xmlSchemaParseRestriction(ctxt, schema, child,
10234 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010235 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010236 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010237 xmlSchemaParseExtension(ctxt, schema, child,
10238 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010239 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010240 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010241 if (child != NULL) {
10242 xmlSchemaPContentErr(ctxt,
10243 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010244 NULL, NULL, node, child, NULL,
10245 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010246 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010247 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010248}
10249
10250/**
10251 * xmlSchemaParseComplexContent:
10252 * @ctxt: a schema validation context
10253 * @schema: the schema being built
10254 * @node: a subtree containing XML Schema informations
10255 *
10256 * parse a XML schema ComplexContent definition
10257 * *WARNING* this interface is highly subject to change
10258 *
10259 * Returns the type definition or NULL in case of error
10260 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010261static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010262xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10263 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010264{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010265 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010266 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010267 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010268
10269 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010270 return (-1);
10271 /* Not a component, don't create it. */
10272 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010273 /*
10274 * Check for illegal attributes.
10275 */
10276 attr = node->properties;
10277 while (attr != NULL) {
10278 if (attr->ns == NULL) {
10279 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010280 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010281 {
10282 xmlSchemaPIllegalAttrErr(ctxt,
10283 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10284 NULL, NULL, attr);
10285 }
10286 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10287 xmlSchemaPIllegalAttrErr(ctxt,
10288 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10289 NULL, NULL, attr);
10290 }
10291 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010292 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010293
10294 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10295
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010296 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010297 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010298 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010299 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10300 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10301 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010302 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010303 child = node->children;
10304 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010305 /*
10306 * Add the annotation to the complex type ancestor.
10307 */
10308 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10309 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010310 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010311 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010312 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010313 xmlSchemaParseRestriction(ctxt, schema, child,
10314 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010315 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010316 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010317 xmlSchemaParseExtension(ctxt, schema, child,
10318 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010319 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010320 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010321 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010322 xmlSchemaPContentErr(ctxt,
10323 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10324 NULL, NULL, node, child,
10325 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010326 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010327 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010328}
10329
10330/**
10331 * xmlSchemaParseComplexType:
10332 * @ctxt: a schema validation context
10333 * @schema: the schema being built
10334 * @node: a subtree containing XML Schema informations
10335 *
10336 * parse a XML schema Complex Type definition
10337 * *WARNING* this interface is highly subject to change
10338 *
10339 * Returns the type definition or NULL in case of error
10340 */
10341static xmlSchemaTypePtr
10342xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010343 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010344{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010345 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010346 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010347 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010348 xmlAttrPtr attr;
10349 const xmlChar *attrValue;
10350 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010351 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010352 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010353
Daniel Veillard4255d502002-04-16 15:50:10 +000010354
10355 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10356 return (NULL);
10357
Daniel Veillard01fa6152004-06-29 17:04:39 +000010358 ctxtType = ctxt->ctxtType;
10359
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010360 if (topLevel) {
10361 attr = xmlSchemaGetPropNode(node, "name");
10362 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010363 xmlSchemaPMissingAttrErr(ctxt,
10364 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010365 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010366 } else if (xmlSchemaPValAttrNode(ctxt,
10367 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010368 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10369 return (NULL);
10370 }
10371 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010372
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010373 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010374 /*
10375 * Parse as local complex type definition.
10376 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010377 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010378 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10379 if (type == NULL)
10380 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010381 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010382 type->node = node;
10383 type->type = XML_SCHEMA_TYPE_COMPLEX;
10384 /*
10385 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010386 */
10387 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010388 /*
10389 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010390 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010391 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010392 if (type == NULL)
10393 return (NULL);
10394 type->node = node;
10395 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010396 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010397 }
10398 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010399 /*
10400 * Handle attributes.
10401 */
10402 attr = node->properties;
10403 while (attr != NULL) {
10404 if (attr->ns == NULL) {
10405 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10406 /*
10407 * Attribute "id".
10408 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010409 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10410 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010411 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10412 /*
10413 * Attribute "mixed".
10414 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010415 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010416 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010417 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10418 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010419 /*
10420 * Attributes of global complex type definitions.
10421 */
10422 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10423 /* Pass. */
10424 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10425 /*
10426 * Attribute "abstract".
10427 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010428 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10429 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010430 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10431 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10432 /*
10433 * Attribute "final".
10434 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010435 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010436 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010437 if (xmlSchemaPValAttrBlockFinal(attrValue,
10438 &(type->flags),
10439 -1,
10440 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10441 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10442 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010443 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010444 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010445 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010446 type, (xmlNodePtr) attr, NULL,
10447 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010448 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010449 } else
10450 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010451 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10452 /*
10453 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010454 */
10455 attrValue = xmlSchemaGetNodeContent(ctxt,
10456 (xmlNodePtr) attr);
10457 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010458 -1,
10459 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010460 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010461 -1, -1, -1) != 0) {
10462 xmlSchemaPSimpleTypeErr(ctxt,
10463 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010464 type, (xmlNodePtr) attr, NULL,
10465 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010466 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010467 } else
10468 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010469 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010470 xmlSchemaPIllegalAttrErr(ctxt,
10471 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010472 &des, type, attr);
10473 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010474 } else {
10475 xmlSchemaPIllegalAttrErr(ctxt,
10476 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010477 &des, type, attr);
10478 }
10479 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010480 xmlSchemaPIllegalAttrErr(ctxt,
10481 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10482 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010483 }
10484 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010485 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010486 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010487 /*
10488 * Apply default "block" values.
10489 */
10490 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10491 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10492 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10493 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10494 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010495 if (! final) {
10496 /*
10497 * Apply default "block" values.
10498 */
10499 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10500 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10501 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10502 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10503 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010504 /*
10505 * And now for the children...
10506 */
10507 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010508 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010509 child = node->children;
10510 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010511 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10512 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010513 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010514 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010515 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010516 /*
10517 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010518 * Specifying mixed='true' when the <simpleContent>
10519 * alternative is chosen has no effect
10520 */
William M. Bracke7091952004-05-11 15:09:58 +000010521 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10522 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010523 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010524 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010525 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010526 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10527 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010528 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010529 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010530 /*
10531 * SPEC
10532 * "...the third alternative (neither <simpleContent> nor
10533 * <complexContent>) is chosen. This case is understood as shorthand
10534 * for complex content restricting the ·ur-type definition·, and the
10535 * details of the mappings should be modified as necessary.
10536 */
10537 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10538 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010539 /*
10540 * Parse model groups.
10541 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010542 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010543 type->subtypes = (xmlSchemaTypePtr)
10544 xmlSchemaParseModelGroup(ctxt, schema, child,
10545 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010546 child = child->next;
10547 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010548 type->subtypes = (xmlSchemaTypePtr)
10549 xmlSchemaParseModelGroup(ctxt, schema, child,
10550 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010551 child = child->next;
10552 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010553 type->subtypes = (xmlSchemaTypePtr)
10554 xmlSchemaParseModelGroup(ctxt, schema, child,
10555 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010556 child = child->next;
10557 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010558 type->subtypes = (xmlSchemaTypePtr)
10559 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010560 child = child->next;
10561 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010562 /*
10563 * Parse attribute decls/refs.
10564 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010565 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010566 /*
10567 * Parse attribute wildcard.
10568 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010569 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010570 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10571 child = child->next;
10572 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010573 }
10574 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010575 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010576 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010577 &des, type, node, child,
10578 NULL, "(annotation?, (simpleContent | complexContent | "
10579 "((group | all | choice | sequence)?, ((attribute | "
10580 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010581 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010582 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010583 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010584 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010585 return (type);
10586}
10587
Daniel Veillard4255d502002-04-16 15:50:10 +000010588/**
10589 * xmlSchemaParseSchema:
10590 * @ctxt: a schema validation context
10591 * @node: a subtree containing XML Schema informations
10592 *
10593 * parse a XML schema definition from a node set
10594 * *WARNING* this interface is highly subject to change
10595 *
10596 * Returns the internal XML Schema structure built from the resource or
10597 * NULL in case of error
10598 */
10599static xmlSchemaPtr
10600xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10601{
10602 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010603 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010604 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010605 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010606
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010607 /*
10608 * This one is called by xmlSchemaParse only and is used if
10609 * the schema to be parsed was specified via the API; i.e. not
10610 * automatically by the validated instance document.
10611 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010612 if ((ctxt == NULL) || (node == NULL))
10613 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010614 nberrors = ctxt->nberrors;
10615 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010616 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010617 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010618 xmlSchemaImportPtr import;
10619
Daniel Veillard4255d502002-04-16 15:50:10 +000010620 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010621 if (schema == NULL)
10622 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010623 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010624 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010625 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010626 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10627 /*
10628 * TODO: Should we proceed with an invalid target namespace?
10629 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010630 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010631 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10632 /*
10633 * We are parsing the schema for schema!
10634 */
10635 ctxt->isS4S = 1;
10636 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010637 } else {
10638 schema->targetNamespace = NULL;
10639 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010640 /*
10641 * Add the current ns name and location to the import table;
10642 * this is needed to have a consistent mechanism, regardless
10643 * if all schemata are constructed dynamically fired by the
10644 * instance or if the schema to be used was specified via
10645 * the API.
10646 */
10647 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10648 schema->targetNamespace);
10649 if (import == NULL) {
10650 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10651 NULL, NULL, (xmlNodePtr) ctxt->doc,
10652 "Internal error: xmlSchemaParseSchema, "
10653 "failed to add an import entry", NULL);
10654 xmlSchemaFree(schema);
10655 schema = NULL;
10656 return (NULL);
10657 }
10658 import->schemaLocation = ctxt->URL;
10659 /*
10660 * NOTE: We won't set the doc here, otherwise it will be freed
10661 * if the import struct is freed.
10662 * import->doc = ctxt->doc;
10663 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010664 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010665 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10666 } else {
10667 xmlDocPtr doc;
10668
10669 doc = node->doc;
10670
10671 if ((doc != NULL) && (doc->URL != NULL)) {
10672 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10673 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010674 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010675 } else {
10676 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10677 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010678 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010679 }
10680 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010681 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010682 if (ctxt->nberrors != 0) {
10683 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010684 xmlSchemaFree(schema);
10685 schema = NULL;
10686 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010687 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010688 if (schema != NULL)
10689 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010690 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010691#ifdef DEBUG
10692 if (schema == NULL)
10693 xmlGenericError(xmlGenericErrorContext,
10694 "xmlSchemaParse() failed\n");
10695#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010696 return (schema);
10697}
10698
10699/************************************************************************
10700 * *
10701 * Validating using Schemas *
10702 * *
10703 ************************************************************************/
10704
10705/************************************************************************
10706 * *
10707 * Reading/Writing Schemas *
10708 * *
10709 ************************************************************************/
10710
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010711#if 0 /* Will be enabled if it is clear what options are needed. */
10712/**
10713 * xmlSchemaParserCtxtSetOptions:
10714 * @ctxt: a schema parser context
10715 * @options: a combination of xmlSchemaParserOption
10716 *
10717 * Sets the options to be used during the parse.
10718 *
10719 * Returns 0 in case of success, -1 in case of an
10720 * API error.
10721 */
10722static int
10723xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10724 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010725
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010726{
10727 int i;
10728
10729 if (ctxt == NULL)
10730 return (-1);
10731 /*
10732 * WARNING: Change the start value if adding to the
10733 * xmlSchemaParseOption.
10734 */
10735 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10736 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010737 return (-1);
10738 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010739 }
10740 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010741 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010742}
10743
10744/**
10745 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010746 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010747 *
10748 * Returns the option combination of the parser context.
10749 */
10750static int
10751xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010752
10753{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010754 if (ctxt == NULL)
10755 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010756 else
10757 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010758}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010759#endif
10760
Daniel Veillard4255d502002-04-16 15:50:10 +000010761/**
10762 * xmlSchemaNewParserCtxt:
10763 * @URL: the location of the schema
10764 *
10765 * Create an XML Schemas parse context for that file/resource expected
10766 * to contain an XML Schemas file.
10767 *
10768 * Returns the parser context or NULL in case of error
10769 */
10770xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010771xmlSchemaNewParserCtxt(const char *URL)
10772{
Daniel Veillard4255d502002-04-16 15:50:10 +000010773 xmlSchemaParserCtxtPtr ret;
10774
10775 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010776 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010777
10778 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10779 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010780 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010781 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010782 return (NULL);
10783 }
10784 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010785 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010786 ret->dict = xmlDictCreate();
10787 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010788 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010789 return (ret);
10790}
10791
10792/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010793 * xmlSchemaNewMemParserCtxt:
10794 * @buffer: a pointer to a char array containing the schemas
10795 * @size: the size of the array
10796 *
10797 * Create an XML Schemas parse context for that memory buffer expected
10798 * to contain an XML Schemas file.
10799 *
10800 * Returns the parser context or NULL in case of error
10801 */
10802xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010803xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10804{
Daniel Veillard6045c902002-10-09 21:13:59 +000010805 xmlSchemaParserCtxtPtr ret;
10806
10807 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010808 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010809
10810 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10811 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010812 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010813 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010814 return (NULL);
10815 }
10816 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10817 ret->buffer = buffer;
10818 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010819 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010820 return (ret);
10821}
10822
10823/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010824 * xmlSchemaNewDocParserCtxt:
10825 * @doc: a preparsed document tree
10826 *
10827 * Create an XML Schemas parse context for that document.
10828 * NB. The document may be modified during the parsing process.
10829 *
10830 * Returns the parser context or NULL in case of error
10831 */
10832xmlSchemaParserCtxtPtr
10833xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10834{
10835 xmlSchemaParserCtxtPtr ret;
10836
10837 if (doc == NULL)
10838 return (NULL);
10839
10840 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10841 if (ret == NULL) {
10842 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10843 NULL);
10844 return (NULL);
10845 }
10846 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10847 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010848 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010849 /* The application has responsibility for the document */
10850 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010851
10852 return (ret);
10853}
10854
10855/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010856 * xmlSchemaFreeParserCtxt:
10857 * @ctxt: the schema parser context
10858 *
10859 * Free the resources associated to the schema parser context
10860 */
10861void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010862xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10863{
Daniel Veillard4255d502002-04-16 15:50:10 +000010864 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010865 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010866 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010867 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010868 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010869 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010870 xmlFree(ctxt->assemble);
10871 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010872 if (ctxt->vctxt != NULL) {
10873 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10874 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010875 if (ctxt->localImports != NULL)
10876 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010877 if (ctxt->substGroups != NULL)
10878 xmlHashFree(ctxt->substGroups,
10879 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010880 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010881 xmlFree(ctxt);
10882}
10883
10884/************************************************************************
10885 * *
10886 * Building the content models *
10887 * *
10888 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010889
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010890static void
10891xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000010892 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010893{
Daniel Veillarda980bef2005-07-18 21:34:03 +000010894 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010895 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010896 xmlSchemaSubstGroupPtr substGroup;
10897 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010898
10899 elemDecl = (xmlSchemaElementPtr) particle->children;
10900 /*
10901 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010902 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010903 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000010904 if (end == NULL)
10905 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010906 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10907 if (substGroup == NULL) {
10908 xmlSchemaPErr(pctxt, GET_NODE(particle),
10909 XML_SCHEMAP_INTERNAL,
10910 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10911 "declaration is marked having a subst. group but none "
10912 "available.\n", elemDecl->name, NULL);
10913 return;
10914 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000010915 if (counter >= 0) {
10916 /*
10917 * NOTE that we put the declaration in, even if it's abstract,
10918 */
10919 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
10920 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10921 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10922 /*
10923 * Add subst. group members.
10924 */
10925 for (i = 0; i < substGroup->members->nbItems; i++) {
10926 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10927 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10928 member->name, member->targetNamespace, member);
10929 }
10930 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010931 /*
10932 * NOTE that we put the declaration in, even if it's abstract,
10933 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010934 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010935 xmlAutomataNewTransition2(pctxt->am,
10936 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010937 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10938 /*
10939 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010940 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010941 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010942 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000010943 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
10944 member->name, member->targetNamespace,
10945 1, 1, member);
10946 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010947 }
10948 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010949 xmlAutomataStatePtr hop;
10950 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10951 UNBOUNDED : particle->maxOccurs - 1;
10952 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10953
10954 counter =
10955 xmlAutomataNewCounter(pctxt->am, minOccurs,
10956 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010957 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010958
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010959 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010960 xmlAutomataNewTransition2(pctxt->am,
10961 start, NULL,
10962 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010963 hop);
10964 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000010965 * Add subst. group members.
10966 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010967 for (i = 0; i < substGroup->members->nbItems; i++) {
10968 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10969 xmlAutomataNewEpsilon(pctxt->am,
10970 xmlAutomataNewTransition2(pctxt->am,
10971 start, NULL,
10972 member->name, member->targetNamespace, member),
10973 hop);
10974 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010975 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10976 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10977 }
10978 if (particle->minOccurs == 0)
10979 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010980 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010981}
10982
10983static void
10984xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10985 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010986{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010987 if (((xmlSchemaElementPtr) particle->children)->flags &
10988 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010989 /*
10990 * Substitution groups.
10991 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000010992 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010993 } else {
10994 xmlSchemaElementPtr elemDecl;
10995 xmlAutomataStatePtr start;
10996
10997 elemDecl = (xmlSchemaElementPtr) particle->children;
10998
10999 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011000 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011001 if (particle->maxOccurs == 1) {
11002 start = ctxt->state;
11003 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011004 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11005 } else if ((particle->maxOccurs >= UNBOUNDED) &&
11006 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011007 /* Special case. */
11008 start = ctxt->state;
11009 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11010 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011011 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011012 } else {
11013 int counter;
11014 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11015 UNBOUNDED : particle->maxOccurs - 1;
11016 int minOccurs = particle->minOccurs < 1 ?
11017 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011018
11019 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011020 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11021 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11022 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11023 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11024 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11025 NULL, counter);
11026 }
11027 if (particle->minOccurs == 0)
11028 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11029 }
11030}
11031
Daniel Veillard4255d502002-04-16 15:50:10 +000011032/**
11033 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011034 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011035 * @particle: the particle component
11036 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011037 *
11038 * Generate the automata sequence needed for that type
11039 */
11040static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011041xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011042 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011043 const xmlChar * name)
11044{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011045 if (particle == NULL) {
11046 xmlSchemaPErr(ctxt, NULL,
11047 XML_SCHEMAP_INTERNAL,
11048 "Internal error: xmlSchemaBuildAContentModel, "
11049 "particle is NULL.\n", NULL, NULL);
11050 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011051 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011052 if (particle->children == NULL) {
11053 xmlSchemaPErr(ctxt, GET_NODE(particle),
11054 XML_SCHEMAP_INTERNAL,
11055 "Internal error: xmlSchemaBuildAContentModel, "
11056 "no term on particle.\n", NULL, NULL);
11057 return;
11058 }
11059
11060 switch (particle->children->type) {
11061 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011062 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011063 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011064 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011065
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011066 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011067
Daniel Veillardc0826a72004-08-10 14:17:33 +000011068 start = ctxt->state;
11069 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011070
11071 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011072 if (wild->any == 1) {
11073 /*
11074 * We need to add both transitions:
11075 *
11076 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011077 */
11078 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011079 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011080 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011081 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11082 /*
11083 * 2. the {"*"} for elements in no namespace.
11084 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011085 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011086 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011087 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011088 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11089
11090 } else if (wild->nsSet != NULL) {
11091 ns = wild->nsSet;
11092 do {
11093 ctxt->state = start;
11094 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011095 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011096 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11097 ns = ns->next;
11098 } while (ns != NULL);
11099
11100 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011101
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011102 /*
11103 * Lead nodes with the negated namespace to the sink-state
11104 * {"*", "##other"}.
11105 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011106 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011107 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011108 /*
11109 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011110 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011111 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011112 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011113 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011114 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011115 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011116 } else {
11117 int counter;
11118 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011119 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011120 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011121 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011122 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011123
Daniel Veillardc0826a72004-08-10 14:17:33 +000011124 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011125 hop = xmlAutomataNewState(ctxt->am);
11126 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011127 ctxt->state =
11128 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011129 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011130 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011131 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011132 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011133 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011134 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011135 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011136 ns = wild->nsSet;
11137 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011138 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011139 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011140 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011141 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11142 ns = ns->next;
11143 } while (ns != NULL);
11144
11145 } else if (wild->negNsSet != NULL) {
Daniel Veillard9efc4762005-07-19 14:33:55 +000011146 ctxt->state = xmlAutomataNewNegTrans(ctxt->am,
11147 start, hop, BAD_CAST "*", wild->negNsSet->value,
11148 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011149 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011150 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11151 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11152 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011153 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011154 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011155 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011156 ctxt->state = end;
11157 break;
11158 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011159 case XML_SCHEMA_TYPE_ELEMENT:
11160 xmlSchemaBuildContentModelForElement(ctxt, particle);
11161 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011162 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011163 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011164
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011165 /*
11166 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011167 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011168 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011169 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11170 sub = particle->children->children;
11171 while (sub != NULL) {
11172 xmlSchemaBuildAContentModel(ctxt,
11173 (xmlSchemaParticlePtr) sub, name);
11174 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011175 }
11176 } else {
11177 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011179 if (particle->maxOccurs >= UNBOUNDED) {
11180 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011181 xmlAutomataStatePtr tmp;
11182 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011183
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011184 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011185 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011186 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011187
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011188 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011189 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011190
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011191 sub = particle->children->children;
11192 while (sub != NULL) {
11193 xmlSchemaBuildAContentModel(ctxt,
11194 (xmlSchemaParticlePtr) sub, name);
11195 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011196 }
11197 tmp = ctxt->state;
11198 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11199 oldstate, counter);
11200 ctxt->state =
11201 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11202 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011203
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011204 } else {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011205 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11206 oldstate, NULL);
11207 oldstate = ctxt->state;
11208
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011209 sub = particle->children->children;
11210 while (sub != NULL) {
11211 xmlSchemaBuildAContentModel(ctxt,
11212 (xmlSchemaParticlePtr) sub, name);
11213 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011214 }
11215 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11216 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011217 /*
11218 * epsilon needed to block previous trans from
11219 * being allowed to enter back from another
11220 * construct
11221 */
11222 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11223 ctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011224 if (particle->minOccurs == 0) {
11225 xmlAutomataNewEpsilon(ctxt->am,
11226 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011227 }
11228 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011229 } else if ((particle->maxOccurs > 1)
11230 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011231 xmlAutomataStatePtr tmp;
11232 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011233
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011234 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011235 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011236 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011237
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011238 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011239 particle->minOccurs - 1,
11240 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011241
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011242 sub = particle->children->children;
11243 while (sub != NULL) {
11244 xmlSchemaBuildAContentModel(ctxt,
11245 (xmlSchemaParticlePtr) sub, name);
11246 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011247 }
11248 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011249 xmlAutomataNewCountedTrans(ctxt->am,
11250 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011251 ctxt->state =
11252 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11253 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011254 if (particle->minOccurs == 0) {
11255 xmlAutomataNewEpsilon(ctxt->am,
11256 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011257 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011258 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011259 sub = particle->children->children;
11260 while (sub != NULL) {
11261 xmlSchemaBuildAContentModel(ctxt,
11262 (xmlSchemaParticlePtr) sub, name);
11263 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011264 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011265 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011266 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11267 ctxt->state);
11268 }
11269 }
11270 }
11271 break;
11272 }
11273 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011274 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011275 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011276
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011277 start = ctxt->state;
11278 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011279
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011280 /*
11281 * iterate over the subtypes and remerge the end with an
11282 * epsilon transition
11283 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011284 if (particle->maxOccurs == 1) {
11285 sub = particle->children->children;
11286 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011287 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011288 xmlSchemaBuildAContentModel(ctxt,
11289 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011290 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011291 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011292 }
11293 } else {
11294 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011295 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011296 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11297 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011298 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011299 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011300
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011301 /*
11302 * use a counter to keep track of the number of transtions
11303 * which went through the choice.
11304 */
11305 counter =
Daniel Veillardafc05b62005-07-17 06:11:19 +000011306 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011307 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011308 base = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011309
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011310 sub = particle->children->children;
11311 while (sub != NULL) {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011312 ctxt->state = base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011313 xmlSchemaBuildAContentModel(ctxt,
11314 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011315 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011316 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011317 }
Daniel Veillardafc05b62005-07-17 06:11:19 +000011318 xmlAutomataNewEpsilon(ctxt->am, start, base);
11319 xmlAutomataNewCountedTrans(ctxt->am, hop, base, counter);
11320 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011321 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011322 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011323 xmlAutomataNewEpsilon(ctxt->am, start, end);
11324 }
11325 ctxt->state = end;
11326 break;
11327 }
11328 case XML_SCHEMA_TYPE_ALL:{
Daniel Veillarda980bef2005-07-18 21:34:03 +000011329 xmlAutomataStatePtr start, hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011330 xmlSchemaParticlePtr sub;
11331 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011332 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011333
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011334 sub = (xmlSchemaParticlePtr) particle->children->children;
11335 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011336 break;
11337 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011338 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011339 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011340
11341 elemDecl = (xmlSchemaElementPtr) sub->children;
11342 if (elemDecl == NULL) {
11343 xmlSchemaPErr(ctxt, NULL,
11344 XML_SCHEMAP_INTERNAL,
11345 "Internal error: xmlSchemaBuildAContentModel, "
11346 "<element> particle a NULL term.\n", NULL, NULL);
11347 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011348 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011349 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011350 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011351 * {particles} of the group must be 0 or 1; this is
11352 * already ensured during the parse of the content of
11353 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011354 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011355 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11356 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011357
Daniel Veillarda980bef2005-07-18 21:34:03 +000011358 /*
11359 * This is an abstract group, we need to share
11360 * the same counter for all the element transitions
11361 * derived from the group
11362 */
11363 counter = xmlAutomataNewCounter(ctxt->am,
11364 sub->minOccurs, sub->maxOccurs);
11365 xmlSchemaBuildContentModelForSubstGroup(ctxt,
11366 sub, counter, ctxt->state);
11367 } else {
11368 if ((sub->minOccurs == 1) &&
11369 (sub->maxOccurs == 1)) {
11370 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11371 ctxt->state,
11372 elemDecl->name,
11373 elemDecl->targetNamespace,
11374 1, 1, elemDecl);
11375 } else if ((sub->minOccurs == 0) &&
11376 (sub->maxOccurs == 1)) {
11377
11378 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11379 ctxt->state,
11380 elemDecl->name,
11381 elemDecl->targetNamespace,
11382 0,
11383 1,
11384 elemDecl);
11385 }
11386 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011387 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011388 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011389 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011390 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011391 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011392 break;
11393 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011394 default:
11395 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011396 "Internal error: xmlSchemaBuildAContentModel, found "
11397 "unexpected term of type %d in content model of complex "
11398 "type '%s'.\n",
11399 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011400 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011401 }
11402}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011403
Daniel Veillard4255d502002-04-16 15:50:10 +000011404/**
11405 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011406 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011407 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011408 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011409 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011410 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011411 */
11412static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011413xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011414 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011415 const xmlChar * name)
11416{
Daniel Veillard4255d502002-04-16 15:50:10 +000011417 xmlAutomataStatePtr start;
11418
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011419 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11420 (type->contModel != NULL) ||
11421 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11422 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011423 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011424
11425#ifdef DEBUG_CONTENT
11426 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011427 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011428#endif
11429
Daniel Veillard4255d502002-04-16 15:50:10 +000011430 ctxt->am = xmlNewAutomata();
11431 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011432 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011433 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011434 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011435 }
11436 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011437 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011438 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011439 type->contModel = xmlAutomataCompile(ctxt->am);
11440 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011441 xmlSchemaPCustomErr(ctxt,
11442 XML_SCHEMAP_INTERNAL,
11443 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011444 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011445 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011446 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011447 XML_SCHEMAP_NOT_DETERMINISTIC,
11448 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011449 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011450 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011451 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011452#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011453 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011454 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011455 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011456#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011457 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011458 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011459 xmlFreeAutomata(ctxt->am);
11460 ctxt->am = NULL;
11461}
11462
11463/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011464 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011465 * @elem: the schema element context
11466 * @ctxt: the schema parser context
11467 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011468 * Resolves the references of an element declaration
11469 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011470 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011471 */
11472static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011473xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011474 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011475 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011476 const xmlChar * context ATTRIBUTE_UNUSED,
11477 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011478{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011479 if ((ctxt == NULL) || (elemDecl == NULL) ||
11480 ((elemDecl != NULL) &&
11481 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011482 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011483 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011484
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011485 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011486 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011487
11488 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011489 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011490 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011491 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011492 elemDecl->namedTypeNs);
11493 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011494 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011495 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011496 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011497 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011498 XML_SCHEMA_TYPE_BASIC, "type definition");
11499 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011500 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011501 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011502 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011503 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011504
Daniel Veillardc0826a72004-08-10 14:17:33 +000011505 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011506 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011507 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011508 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011509 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11510 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011511 if (substHead == NULL) {
11512 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011513 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011514 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011515 "substitutionGroup", elemDecl->substGroup,
11516 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011517 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011518 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011519 /*
11520 * Set the "substitution group affiliation".
11521 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011522 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011523 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011524 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011525 * (type definition)...otherwise the {type definition} of the
11526 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011527 * the substitutionGroup [attribute], if present
11528 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011529 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011530 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011531 }
11532 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011533 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11534 (elemDecl->substGroup == NULL))
11535 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011536}
11537
11538/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011539 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011540 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011541 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011542 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011543 * Checks and builds the "member type definitions" property of the union
11544 * simple type. This handles part (1), part (2) is done in
11545 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11546 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011547 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011548 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011549static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011550xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11551 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011552{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011553
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011554 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011555 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011556
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011557 /*
11558 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11559 * define the explicit members as the type definitions ·resolved·
11560 * to by the items in the ·actual value· of the memberTypes [attribute],
11561 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011562 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011563 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011564 /*
11565 * Resolve references.
11566 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011567 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011568 lastLink = NULL;
11569 while (link != NULL) {
11570 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011571
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011572 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11573 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11574
11575 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11576 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11577 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011578 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011579 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11580 /*
11581 * Remove the member type link.
11582 */
11583 if (lastLink == NULL)
11584 type->memberTypes = link->next;
11585 else
11586 lastLink->next = link->next;
11587 newLink = link;
11588 link = link->next;
11589 xmlFree(newLink);
11590 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011591 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011592 lastLink = link;
11593 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011594 }
11595 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011596 /*
11597 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011598 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011599 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011600 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011601 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11602 if (link == NULL) {
11603 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11604 return (-1);
11605 }
11606 link->type = memberType;
11607 link->next = NULL;
11608 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011609 type->memberTypes = link;
11610 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011611 lastLink->next = link;
11612 lastLink = link;
11613 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011614 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011615 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011616}
11617
Daniel Veillard4255d502002-04-16 15:50:10 +000011618/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011619 * xmlSchemaIsDerivedFromBuiltInType:
11620 * @ctxt: the schema parser context
11621 * @type: the type definition
11622 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011623 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011624 *
11625 * Returns 1 if the type has the given value type, or
11626 * is derived from such a type.
11627 */
William M. Brack803812b2004-06-03 02:11:24 +000011628static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011629xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011630{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011631 if (type == NULL)
11632 return (0);
11633 if (IS_COMPLEX_TYPE(type))
11634 return (0);
11635 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11636 if (type->builtInType == valType)
11637 return(1);
11638 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11639 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11640 return (0);
11641 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11642 } else
11643 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011644
11645 return (0);
11646}
11647
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011648#if 0
11649/**
11650 * xmlSchemaIsDerivedFromBuiltInType:
11651 * @ctxt: the schema parser context
11652 * @type: the type definition
11653 * @valType: the value type
11654 *
11655 *
11656 * Returns 1 if the type has the given value type, or
11657 * is derived from such a type.
11658 */
11659static int
11660xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11661{
11662 if (type == NULL)
11663 return (0);
11664 if (IS_COMPLEX_TYPE(type))
11665 return (0);
11666 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11667 if (type->builtInType == valType)
11668 return(1);
11669 return (0);
11670 } else
11671 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11672
11673 return (0);
11674}
11675#endif
11676
11677static xmlSchemaTypePtr
11678xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11679{
11680 if (type == NULL)
11681 return (NULL);
11682 if (IS_COMPLEX_TYPE(type))
11683 return (NULL);
11684 if (type->type == XML_SCHEMA_TYPE_BASIC)
11685 return(type);
11686 else
11687 return(xmlSchemaQueryBuiltInType(type->subtypes));
11688
11689 return (NULL);
11690}
11691
Daniel Veillard3646d642004-06-02 19:19:14 +000011692/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011693 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011694 * @type: the simpleType definition
11695 *
11696 * Returns the primitive type of the given type or
11697 * NULL in case of error.
11698 */
11699static xmlSchemaTypePtr
11700xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11701{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011702
Daniel Veillard01fa6152004-06-29 17:04:39 +000011703 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011704 /*
11705 * Note that anySimpleType is actually not a primitive type
11706 * but we need that here.
11707 */
11708 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11709 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011710 return (type);
11711 type = type->baseType;
11712 }
11713
11714 return (NULL);
11715}
11716
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011717#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011718/**
11719 * xmlSchemaGetBuiltInTypeAncestor:
11720 * @type: the simpleType definition
11721 *
11722 * Returns the primitive type of the given type or
11723 * NULL in case of error.
11724 */
11725static xmlSchemaTypePtr
11726xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11727{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011728 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011729 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011730 while (type != NULL) {
11731 if (type->type == XML_SCHEMA_TYPE_BASIC)
11732 return (type);
11733 type = type->baseType;
11734 }
11735
11736 return (NULL);
11737}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011738#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011739
Daniel Veillard01fa6152004-06-29 17:04:39 +000011740/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011741 * xmlSchemaBuildAttributeUsesOwned:
11742 * @ctxt: the schema parser context
11743 * @type: the complex type definition
11744 * @cur: the attribute declaration list
11745 * @lastUse: the top of the attribute use list
11746 *
11747 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011748 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011749 * xmlSchemaBuildAttributeValidation only.
11750 */
11751static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011752xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011753 xmlSchemaAttributePtr cur,
11754 xmlSchemaAttributeLinkPtr *uses,
11755 xmlSchemaAttributeLinkPtr *lastUse)
11756{
11757 xmlSchemaAttributeLinkPtr tmp;
11758 while (cur != NULL) {
11759 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011760 /*
11761 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11762 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011763 * <attributeGroup> [children], if any."
11764 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011765 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11766 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011767 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011768 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011769 }
11770 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011771 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011772 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011773 */
11774 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011775 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11776 if (tmp == NULL) {
11777 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11778 return (-1);
11779 }
11780 tmp->attr = cur;
11781 tmp->next = NULL;
11782 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011783 *uses = tmp;
11784 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011785 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011786 *lastUse = tmp;
11787 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011788 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011789 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011790 return (0);
11791}
11792
Daniel Veillard50355f02004-06-08 17:52:16 +000011793/**
11794 * xmlSchemaCloneWildcardNsConstraints:
11795 * @ctxt: the schema parser context
11796 * @dest: the destination wildcard
11797 * @source: the source wildcard
11798 *
11799 * Clones the namespace constraints of source
11800 * and assignes them to dest.
11801 * Returns -1 on internal error, 0 otherwise.
11802 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011803static int
11804xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11805 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011806 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011807{
11808 xmlSchemaWildcardNsPtr cur, tmp, last;
11809
11810 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011811 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011812 (*dest)->any = source->any;
11813 cur = source->nsSet;
11814 last = NULL;
11815 while (cur != NULL) {
11816 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11817 if (tmp == NULL)
11818 return(-1);
11819 tmp->value = cur->value;
11820 if (last == NULL)
11821 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011822 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011823 last->next = tmp;
11824 last = tmp;
11825 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011826 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011827 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011828 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011829 if (source->negNsSet != NULL) {
11830 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11831 if ((*dest)->negNsSet == NULL)
11832 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011833 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011834 } else
11835 (*dest)->negNsSet = NULL;
11836 return(0);
11837}
11838
Daniel Veillard50355f02004-06-08 17:52:16 +000011839/**
11840 * xmlSchemaUnionWildcards:
11841 * @ctxt: the schema parser context
11842 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011843 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011844 *
11845 * Unions the namespace constraints of the given wildcards.
11846 * @completeWild will hold the resulting union.
11847 * Returns a positive error code on failure, -1 in case of an
11848 * internal error, 0 otherwise.
11849 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011850static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011851xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011852 xmlSchemaWildcardPtr completeWild,
11853 xmlSchemaWildcardPtr curWild)
11854{
11855 xmlSchemaWildcardNsPtr cur, curB, tmp;
11856
11857 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011858 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011859 * value.
11860 */
11861 if ((completeWild->any == curWild->any) &&
11862 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11863 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011864
Daniel Veillard3646d642004-06-02 19:19:14 +000011865 if ((completeWild->negNsSet == NULL) ||
11866 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011867
Daniel Veillard3646d642004-06-02 19:19:14 +000011868 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011869 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011870
11871 /*
11872 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011873 */
11874 cur = completeWild->nsSet;
11875 while (cur != NULL) {
11876 found = 0;
11877 curB = curWild->nsSet;
11878 while (curB != NULL) {
11879 if (cur->value == curB->value) {
11880 found = 1;
11881 break;
11882 }
11883 curB = curB->next;
11884 }
11885 if (!found)
11886 break;
11887 cur = cur->next;
11888 }
11889 if (found)
11890 return(0);
11891 } else
11892 return(0);
11893 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011894 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011895 /*
11896 * 2 If either O1 or O2 is any, then any must be the value
11897 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011898 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011899 if (completeWild->any == 0) {
11900 completeWild->any = 1;
11901 if (completeWild->nsSet != NULL) {
11902 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11903 completeWild->nsSet = NULL;
11904 }
11905 if (completeWild->negNsSet != NULL) {
11906 xmlFree(completeWild->negNsSet);
11907 completeWild->negNsSet = NULL;
11908 }
11909 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011910 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011911 }
11912 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011913 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011914 * then the union of those sets must be the value.
11915 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011916 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011917 int found;
11918 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011919
Daniel Veillard3646d642004-06-02 19:19:14 +000011920 cur = curWild->nsSet;
11921 start = completeWild->nsSet;
11922 while (cur != NULL) {
11923 found = 0;
11924 curB = start;
11925 while (curB != NULL) {
11926 if (cur->value == curB->value) {
11927 found = 1;
11928 break;
11929 }
11930 curB = curB->next;
11931 }
11932 if (!found) {
11933 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011934 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011935 return (-1);
11936 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011937 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011938 completeWild->nsSet = tmp;
11939 }
11940 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011941 }
11942
Daniel Veillard3646d642004-06-02 19:19:14 +000011943 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011944 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011945 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011946 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011947 * or ·absent·), then a pair of not and ·absent· must be the value.
11948 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011949 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011950 (curWild->negNsSet != NULL) &&
11951 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11952 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011953
11954 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011955 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011956 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011957 * 5.
11958 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011959 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011960 (completeWild->negNsSet->value != NULL) &&
11961 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011962 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011963 (curWild->negNsSet->value != NULL) &&
11964 (completeWild->nsSet != NULL))) {
11965
11966 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011967
Daniel Veillard3646d642004-06-02 19:19:14 +000011968 if (completeWild->nsSet != NULL) {
11969 cur = completeWild->nsSet;
11970 curB = curWild->negNsSet;
11971 } else {
11972 cur = curWild->nsSet;
11973 curB = completeWild->negNsSet;
11974 }
11975 nsFound = 0;
11976 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011977 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011978 absentFound = 1;
11979 else if (cur->value == curB->value)
11980 nsFound = 1;
11981 if (nsFound && absentFound)
11982 break;
11983 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011984 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011985
11986 if (nsFound && absentFound) {
11987 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011988 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011989 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011990 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011991 completeWild->any = 1;
11992 if (completeWild->nsSet != NULL) {
11993 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11994 completeWild->nsSet = NULL;
11995 }
11996 if (completeWild->negNsSet != NULL) {
11997 xmlFree(completeWild->negNsSet);
11998 completeWild->negNsSet = NULL;
11999 }
12000 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012001 /*
12002 * 5.2 If the set S includes the negated namespace name
12003 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000012004 * be the value.
12005 */
12006 if (completeWild->nsSet != NULL) {
12007 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12008 completeWild->nsSet = NULL;
12009 }
12010 if (completeWild->negNsSet == NULL) {
12011 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12012 if (completeWild->negNsSet == NULL)
12013 return (-1);
12014 }
12015 completeWild->negNsSet->value = NULL;
12016 } else if ((!nsFound) && absentFound) {
12017 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012018 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012019 * namespace name, then the union is not expressible.
12020 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012021 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012022 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012023 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012024 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012025 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012026 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012027 /*
12028 * 5.4 If the set S does not include either the negated namespace
12029 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012030 * and a namespace name must be the value.
12031 */
12032 if (completeWild->negNsSet == NULL) {
12033 if (completeWild->nsSet != NULL) {
12034 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12035 completeWild->nsSet = NULL;
12036 }
12037 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12038 if (completeWild->negNsSet == NULL)
12039 return (-1);
12040 completeWild->negNsSet->value = curWild->negNsSet->value;
12041 }
12042 }
12043 return (0);
12044 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012045 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012046 * 6.
12047 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012048 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012049 (completeWild->negNsSet->value == NULL) &&
12050 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012051 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012052 (curWild->negNsSet->value == NULL) &&
12053 (completeWild->nsSet != NULL))) {
12054
12055 if (completeWild->nsSet != NULL) {
12056 cur = completeWild->nsSet;
12057 } else {
12058 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012059 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012060 while (cur != NULL) {
12061 if (cur->value == NULL) {
12062 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012063 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012064 * value.
12065 */
12066 completeWild->any = 1;
12067 if (completeWild->nsSet != NULL) {
12068 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12069 completeWild->nsSet = NULL;
12070 }
12071 if (completeWild->negNsSet != NULL) {
12072 xmlFree(completeWild->negNsSet);
12073 completeWild->negNsSet = NULL;
12074 }
12075 return (0);
12076 }
12077 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012078 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012079 if (completeWild->negNsSet == NULL) {
12080 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012081 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012082 * and ·absent· must be the value.
12083 */
12084 if (completeWild->nsSet != NULL) {
12085 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12086 completeWild->nsSet = NULL;
12087 }
12088 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12089 if (completeWild->negNsSet == NULL)
12090 return (-1);
12091 completeWild->negNsSet->value = NULL;
12092 }
12093 return (0);
12094 }
12095 return (0);
12096
12097}
12098
Daniel Veillard50355f02004-06-08 17:52:16 +000012099/**
12100 * xmlSchemaIntersectWildcards:
12101 * @ctxt: the schema parser context
12102 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012103 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012104 *
12105 * Intersects the namespace constraints of the given wildcards.
12106 * @completeWild will hold the resulting intersection.
12107 * Returns a positive error code on failure, -1 in case of an
12108 * internal error, 0 otherwise.
12109 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012110static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012111xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012112 xmlSchemaWildcardPtr completeWild,
12113 xmlSchemaWildcardPtr curWild)
12114{
William M. Brack803812b2004-06-03 02:11:24 +000012115 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012116
12117 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012118 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012119 * value.
12120 */
12121 if ((completeWild->any == curWild->any) &&
12122 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12123 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012124
Daniel Veillard3646d642004-06-02 19:19:14 +000012125 if ((completeWild->negNsSet == NULL) ||
12126 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012127
Daniel Veillard3646d642004-06-02 19:19:14 +000012128 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012129 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012130
12131 /*
12132 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012133 */
12134 cur = completeWild->nsSet;
12135 while (cur != NULL) {
12136 found = 0;
12137 curB = curWild->nsSet;
12138 while (curB != NULL) {
12139 if (cur->value == curB->value) {
12140 found = 1;
12141 break;
12142 }
12143 curB = curB->next;
12144 }
12145 if (!found)
12146 break;
12147 cur = cur->next;
12148 }
12149 if (found)
12150 return(0);
12151 } else
12152 return(0);
12153 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012154 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012155 /*
12156 * 2 If either O1 or O2 is any, then the other must be the value.
12157 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012158 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012159 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012160 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012161 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012162 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012163 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012164 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12165 * name or ·absent·) and the other is a set of (namespace names or
12166 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012167 * the set, minus ·absent· if it was in the set, must be the value.
12168 */
12169 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12170 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12171 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012172
Daniel Veillard3646d642004-06-02 19:19:14 +000012173 if (completeWild->nsSet == NULL) {
12174 neg = completeWild->negNsSet->value;
12175 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12176 return(-1);
12177 } else
12178 neg = curWild->negNsSet->value;
12179 /*
12180 * Remove absent and negated.
12181 */
12182 prev = NULL;
12183 cur = completeWild->nsSet;
12184 while (cur != NULL) {
12185 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012186 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012187 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012188 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012189 prev->next = cur->next;
12190 xmlFree(cur);
12191 break;
12192 }
12193 prev = cur;
12194 cur = cur->next;
12195 }
12196 if (neg != NULL) {
12197 prev = NULL;
12198 cur = completeWild->nsSet;
12199 while (cur != NULL) {
12200 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012201 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012202 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012203 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012204 prev->next = cur->next;
12205 xmlFree(cur);
12206 break;
12207 }
12208 prev = cur;
12209 cur = cur->next;
12210 }
12211 }
12212
12213 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012214 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012215 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012216 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012217 * then the intersection of those sets must be the value.
12218 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012219 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012220 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012221
Daniel Veillard3646d642004-06-02 19:19:14 +000012222 cur = completeWild->nsSet;
12223 prev = NULL;
12224 while (cur != NULL) {
12225 found = 0;
12226 curB = curWild->nsSet;
12227 while (curB != NULL) {
12228 if (cur->value == curB->value) {
12229 found = 1;
12230 break;
12231 }
12232 curB = curB->next;
12233 }
12234 if (!found) {
12235 if (prev == NULL)
12236 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012237 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012238 prev->next = cur->next;
12239 tmp = cur->next;
12240 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012241 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012242 continue;
12243 }
12244 prev = cur;
12245 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012246 }
12247
Daniel Veillard3646d642004-06-02 19:19:14 +000012248 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012249 }
12250 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012251 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012252 */
12253 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012254 (curWild->negNsSet != NULL) &&
12255 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012256 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012257 (curWild->negNsSet->value != NULL)) {
12258
12259 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012260 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012261 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012262 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012263 }
12264 /*
12265 * 6 If the one is a negation of a namespace name and the other
12266 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012267 * of a namespace name must be the value.
12268 */
12269 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12270 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012271 (completeWild->negNsSet->value == NULL)) {
12272 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012273 }
12274 return(0);
12275}
12276
Daniel Veillard50355f02004-06-08 17:52:16 +000012277/**
12278 * xmlSchemaIsWildcardNsConstraintSubset:
12279 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012280 * @sub: the first wildcard
12281 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012282 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012283 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12284 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012285 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012286 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012287 */
12288static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012289xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12290 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012291{
Daniel Veillard50355f02004-06-08 17:52:16 +000012292 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012293 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012294 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012295 if (super->any)
12296 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012297 /*
12298 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12299 * 2.2 super must be a pair of not and the same value.
12300 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012301 if ((sub->negNsSet != NULL) &&
12302 (super->negNsSet != NULL) &&
12303 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012304 return (0);
12305 /*
12306 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012307 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012308 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012309 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012310 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012311 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012312 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012313 xmlSchemaWildcardNsPtr cur, curB;
12314 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012315
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012316 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012317 while (cur != NULL) {
12318 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012319 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012320 while (curB != NULL) {
12321 if (cur->value == curB->value) {
12322 found = 1;
12323 break;
12324 }
12325 curB = curB->next;
12326 }
12327 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012328 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012329 cur = cur->next;
12330 }
12331 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012332 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012333 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012334 xmlSchemaWildcardNsPtr cur;
12335 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012336 * 3.2.2 super must be a pair of not and a namespace name or
12337 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012338 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012339 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012340 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012341 if (cur->value == super->negNsSet->value)
12342 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012343 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012344 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012345 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012346 }
12347 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012348 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012349}
12350
12351/**
12352 * xmlSchemaBuildCompleteAttributeWildcard:
12353 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012354 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012355 * @completeWild: the resulting complete wildcard
12356 *
12357 * Returns -1 in case of an internal error, 0 otherwise.
12358 */
12359static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012360xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012361 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012362 xmlSchemaWildcardPtr *completeWild)
12363{
Daniel Veillard3646d642004-06-02 19:19:14 +000012364 while (attrs != NULL) {
12365 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12366 xmlSchemaAttributeGroupPtr group;
12367
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012368 group = (xmlSchemaAttributeGroupPtr) attrs;
12369 /*
12370 * Handle attribute group references.
12371 */
12372 if (group->ref != NULL) {
12373 if (group->refItem == NULL) {
12374 /*
12375 * TODO: Should we raise a warning here?
12376 */
12377 /*
12378 * The referenced attribute group definition could not
12379 * be resolved beforehand, so skip.
12380 */
12381 attrs = attrs->next;
12382 continue;
12383 } else
12384 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012385 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012386 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012387 * For every attribute group definition, an intersected wildcard
12388 * will be created (assumed that a wildcard exists on the
12389 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012390 * at all).
12391 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12392 * that the intersection will be performed only once.
12393 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012394 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12395 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012396 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012397 group->attributes, &group->attributeWildcard) == -1)
12398 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012399 }
12400 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012401 }
12402 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012403 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012404 /*
12405 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012406 *
12407 * Although the complete wildcard might not correspond to any
12408 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012409 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012410 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12411 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12412 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012413 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012414 completeWild, group->attributeWildcard) == -1)
12415 return (-1);
12416 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012417 (*completeWild)->node = group->attributeWildcard->node;
12418 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012419 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012420 }
12421 }
12422 attrs = attrs->next;
12423 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012424
12425 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012426}
12427
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012428static int
12429xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12430 int *fixed,
12431 const xmlChar **value,
12432 xmlSchemaValPtr *val)
12433{
12434 *fixed = 0;
12435 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012436 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012437 *val = NULL;
12438
12439 if (item->defValue == NULL)
12440 item = item->refDecl;
12441
12442 if (item == NULL)
12443 return (0);
12444
12445 if (item->defValue != NULL) {
12446 *value = item->defValue;
12447 if (val != 0)
12448 *val = item->defVal;
12449 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12450 *fixed = 1;
12451 return (1);
12452 }
12453 return (0);
12454}
Daniel Veillard3646d642004-06-02 19:19:14 +000012455/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012456 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012457 * @wild: the wildcard
12458 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012459 *
12460 * Validation Rule: Wildcard allows Namespace Name
12461 * (cvc-wildcard-namespace)
12462 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012463 *
12464 * Returns 1 if the given namespace matches the wildcard,
12465 * 0 otherwise.
12466 */
12467static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012468xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12469 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012470{
12471 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012472 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012473
12474 if (wild->any)
12475 return(1);
12476 else if (wild->nsSet != NULL) {
12477 xmlSchemaWildcardNsPtr cur;
12478
12479 cur = wild->nsSet;
12480 while (cur != NULL) {
12481 if (xmlStrEqual(cur->value, ns))
12482 return(1);
12483 cur = cur->next;
12484 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012485 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012486 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012487 return(1);
12488
Daniel Veillard3646d642004-06-02 19:19:14 +000012489 return(0);
12490}
12491
12492/**
12493 * xmlSchemaBuildAttributeValidation:
12494 * @ctxt: the schema parser context
12495 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012496 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012497 *
12498 * Builds the wildcard and the attribute uses on the given complex type.
12499 * Returns -1 if an internal error occurs, 0 otherwise.
12500 */
12501static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012502xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12503 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012504{
12505 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012506 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12507 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012508 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012509 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012510 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012511 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012512
Daniel Veillard01fa6152004-06-29 17:04:39 +000012513 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012514 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012515 * Complex Type Definition with complex content Schema Component.
12516 *
12517 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012518 * TODO: Add checks for absent referenced attribute declarations and
12519 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012520 */
12521 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012522 PERROR_INT("xmlSchemaBuildAttributeValidation",
12523 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012524 return (-1);
12525 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012526 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012527 PERROR_INT("xmlSchemaBuildAttributeValidation",
12528 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012529 return (-1);
12530 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012531 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012532 /*
12533 * Inherit the attribute uses of the base type.
12534 */
12535 /*
12536 * NOTE: It is allowed to "extend" the anyType complex type.
12537 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012538 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012539 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012540 for (cur = baseType->attributeUses; cur != NULL;
12541 cur = cur->next) {
12542 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012543 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12544 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012545 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012546 "building attribute uses of complexType", NULL);
12547 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012548 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012549 tmp->attr = cur->attr;
12550 tmp->next = NULL;
12551 if (type->attributeUses == NULL) {
12552 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012553 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012554 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012555 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012556 }
12557 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012558 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012559 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012560 /*
12561 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012562 */
12563 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12564 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012565 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012566 * NOTE: During the parse time, the wildcard is created on the complexType
12567 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012568 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012569 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012570 PERROR_INT("xmlSchemaBuildAttributeValidation",
12571 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012572 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012573 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012574
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012575 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12576 ((IS_ANYTYPE(baseType)) ||
12577 ((baseType != NULL) &&
12578 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12579 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012580 if (type->attributeWildcard != NULL) {
12581 /*
12582 * Union the complete wildcard with the base wildcard.
12583 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012584 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012585 baseType->attributeWildcard) == -1)
12586 return (-1);
12587 } else {
12588 /*
12589 * Just inherit the wildcard.
12590 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012591 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012592 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012593 * wildcard is shared.
12594 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012595 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012596 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012597 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012598
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012599 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12600 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012601 /*
12602 * Derivation Valid (Restriction, Complex)
12603 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012604 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012605 if (baseType->attributeWildcard == NULL) {
12606 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012607 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012608 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012609 "The type has an attribute wildcard, "
12610 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012611 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012612 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012613 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012614 } else if (xmlSchemaCheckCOSNSSubset(
12615 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012616 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012617 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012618 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012619 NULL, type, NULL,
12620 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012621 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012622 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12623 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012624 return (1);
12625 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012626 /* 4.3 Unless the {base type definition} is the ·ur-type
12627 * definition·, the complex type definition's {attribute
12628 * wildcard}'s {process contents} must be identical to or
12629 * stronger than the {base type definition}'s {attribute
12630 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012631 * than lax is stronger than skip.
12632 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012633 if ((! IS_ANYTYPE(baseType)) &&
12634 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012635 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012636 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012637 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012638 NULL, type, NULL,
12639 "The 'process contents' of the attribute wildcard is "
12640 "weaker than the one in the base type %s",
12641 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012642 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012643 return (1);
12644 }
12645 }
12646 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12647 /*
12648 * Derivation Valid (Extension)
12649 * At this point the type and the base have both, either
12650 * no wildcard or a wildcard.
12651 */
12652 if ((baseType->attributeWildcard != NULL) &&
12653 (baseType->attributeWildcard != type->attributeWildcard)) {
12654 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012655 if (xmlSchemaCheckCOSNSSubset(
12656 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012657 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012658 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012659 NULL, type, NULL,
12660 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012661 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012662 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12663 FREE_AND_NULL(str)
12664 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012665 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012666 }
12667 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012668
Daniel Veillard3646d642004-06-02 19:19:14 +000012669 /*
12670 * Gather attribute uses defined by this type.
12671 */
12672 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012673 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012674 &uses, &lastUse) == -1) {
12675 return (-1);
12676 }
12677 }
12678 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012679 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012680 * not have identical {name}s and {target namespace}s."
12681 *
12682 * For "extension" this is done further down.
12683 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012684 if ((uses != NULL) && ((type->flags &
12685 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012686 cur = uses;
12687 while (cur != NULL) {
12688 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012689 while (tmp != NULL) {
12690 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012691 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012692 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012693 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12694
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012695 xmlSchemaPAttrUseErr(pctxt,
12696 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12697 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012698 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012699 xmlSchemaFormatQName(&str,
12700 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12701 xmlSchemaGetAttrName(tmp->attr)));
12702 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012703 break;
12704 }
12705 tmp = tmp->next;
12706 }
12707 cur = cur->next;
12708 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012709 }
12710 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012711 /*
12712 * Derive by restriction.
12713 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012714 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012715 type->attributeUses = uses;
12716 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012717 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012718 const xmlChar *bEffValue;
12719 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012720
12721 cur = uses;
12722 while (cur != NULL) {
12723 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012724 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012725 base = type->attributeUses;
12726 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012727 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012728 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012729 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012730 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012731
12732 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012733
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012734 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012735 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12736 (base->attr->occurs ==
12737 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12738 /*
12739 * NOOP.
12740 */
12741 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012742 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12743 (base->attr->occurs ==
12744 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012745 /*
12746 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012747 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012748 xmlSchemaPAttrUseErr(pctxt,
12749 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12750 type, cur->attr,
12751 "The 'optional' use is inconsistent with a "
12752 "matching 'required' use of the base type",
12753 NULL);
12754 } else if ((cur->attr->occurs ==
12755 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12756 (base->attr->occurs ==
12757 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12758 /*
12759 * derivation-ok-restriction 3
12760 */
12761 xmlSchemaPCustomErr(pctxt,
12762 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12763 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012764 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012765 "attribute use '%s' of the base type is "
12766 "missing",
12767 xmlSchemaFormatQName(&str,
12768 xmlSchemaGetAttrTargetNsURI(base->attr),
12769 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012770 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012771 } else if (xmlSchemaCheckCOSSTDerivedOK(
12772 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12773
12774 /*
12775 * SPEC (2.1.2) "R's {attribute declaration}'s
12776 * {type definition} must be validly derived from
12777 * B's {type definition} given the empty set as
12778 * defined in Type Derivation OK (Simple) (§3.14.6)."
12779 */
12780 xmlSchemaPAttrUseErr(pctxt,
12781 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12782 type, cur->attr,
12783 "The attribute declaration's type "
12784 "definition is not validly derived from "
12785 "the corresponding definition in the "
12786 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012787 } else {
12788 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012789 * 2.1.3 [Definition:] Let the effective value
12790 * constraint of an attribute use be its {value
12791 * constraint}, if present, otherwise its {attribute
12792 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012793 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012794 xmlSchemaGetEffectiveValueConstraint(base->attr,
12795 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012796 /*
12797 * 2.1.3 ... one of the following must be true
12798 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012799 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012800 * ·absent· or default.
12801 */
12802 if ((bEffValue != NULL) &&
12803 (effFixed == 1)) {
12804 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012805
12806 xmlSchemaGetEffectiveValueConstraint(base->attr,
12807 &effFixed, &rEffValue, 0);
12808 /*
12809 * 2.1.3.2 R's ·effective value constraint· is
12810 * fixed with the same string as B's.
12811 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012812 */
12813 if ((effFixed == 0) ||
12814 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012815 xmlSchemaPAttrUseErr(pctxt,
12816 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12817 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012818 "The effective value constraint of the "
12819 "attribute use is inconsistent with "
12820 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012821 NULL);
12822 } else {
12823 /*
12824 * Override the attribute use.
12825 */
12826 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012827 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012828 } else
12829 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012830 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012831
Daniel Veillard3646d642004-06-02 19:19:14 +000012832 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012833 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012834 base = base->next;
12835 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012836
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012837 if ((!found) && (cur->attr->occurs !=
12838 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12839 /*
12840 * derivation-ok-restriction 2.2
12841 */
12842 if ((baseType->attributeWildcard == NULL) ||
12843 (xmlSchemaCheckCVCWildcardNamespace(
12844 baseType->attributeWildcard,
12845 cur->attr->targetNamespace) != 1)) {
12846 xmlSchemaPAttrUseErr(pctxt,
12847 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12848 type, cur->attr,
12849 "Neither a matching attribute use, "
12850 "nor a matching wildcard in the base type does exist",
12851 NULL);
12852 } else {
12853 /*
12854 * Add the attribute use.
12855 *
12856 * Note that this may lead to funny derivation error reports, if
12857 * multiple equal attribute uses exist; but this is not
12858 * allowed anyway, and it will be reported beforehand.
12859 */
12860 tmp = cur;
12861 if (prev != NULL)
12862 prev->next = cur->next;
12863 else
12864 uses = cur->next;
12865 cur = cur->next;
12866 tmp->next = NULL;
12867 if (type->attributeUses == NULL) {
12868 type->attributeUses = tmp;
12869 } else
12870 lastBaseUse->next = tmp;
12871 lastBaseUse = tmp;
12872
12873 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012874 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012875 }
12876 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012877 cur = cur->next;
12878 }
12879 if (uses != NULL)
12880 xmlSchemaFreeAttributeUseList(uses);
12881 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012882 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012883 /*
12884 * The spec allows only appending, and not other kinds of extensions.
12885 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012886 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012887 */
12888 if (uses != NULL) {
12889 if (type->attributeUses == NULL) {
12890 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012891 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012892 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012893 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012894 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012895 PERROR_INT("xmlSchemaBuildAttributeValidation",
12896 "no derivation method");
12897 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012898 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012899 /*
12900 * 3.4.6 -> Complex Type Definition Properties Correct
12901 */
12902 if (type->attributeUses != NULL) {
12903 cur = type->attributeUses;
12904 prev = NULL;
12905 while (cur != NULL) {
12906 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012907 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012908 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012909 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012910 * Note that this was already done for "restriction" and types derived from
12911 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012912 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012913 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12914 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012915 while (tmp != NULL) {
12916 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012917 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012918 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012919 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012920
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012921 xmlSchemaPAttrUseErr(pctxt,
12922 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12923 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012924 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012925 break;
12926 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012927 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012928 }
12929 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012930 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012931 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012932 * not have {type definition}s which are or are derived from ID.
12933 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012934 if ((cur->attr->subtypes != NULL) &&
12935 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12936 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012937 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012938 xmlSchemaPAttrUseErr(pctxt,
12939 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12940 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012941 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012942 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012943 NULL);
12944 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012945 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012946 id = cur;
12947 }
12948 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012949 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012950 * stage is to be able to catch dublicate attribute uses. So we had to keep
12951 * prohibited uses in the list as well.
12952 */
12953 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12954 tmp = cur;
12955 if (prev == NULL)
12956 type->attributeUses = cur->next;
12957 else
12958 prev->next = cur->next;
12959 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012960 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012961 } else {
12962 prev = cur;
12963 cur = cur->next;
12964 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012965 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012966 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012967 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012968 * TODO: This check should be removed if we are 100% sure of
12969 * the base type attribute uses already being built.
12970 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012971 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012972 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012973 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012974 PERROR_INT("xmlSchemaBuildAttributeValidation",
12975 "attribute uses not builded on base type");
12976 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012977 return (0);
12978}
12979
12980/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012981 * xmlSchemaTypeFinalContains:
12982 * @schema: the schema
12983 * @type: the type definition
12984 * @final: the final
12985 *
12986 * Evaluates if a type definition contains the given "final".
12987 * This does take "finalDefault" into account as well.
12988 *
12989 * Returns 1 if the type does containt the given "final",
12990 * 0 otherwise.
12991 */
12992static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012993xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012994{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012995 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012996 return (0);
12997 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012998 return (1);
12999 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013000 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013001}
13002
13003/**
13004 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13005 * @type: the Union Simple Type
13006 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013007 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013008 * returns NULL otherwise.
13009 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013010static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013011xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13012{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013013 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013014 if (type->memberTypes != NULL)
13015 return (type->memberTypes);
13016 else
13017 type = type->baseType;
13018 }
13019 return (NULL);
13020}
13021
13022/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013023 * xmlSchemaGetParticleTotalRangeMin:
13024 * @particle: the particle
13025 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013026 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013027 * (all and sequence) + (choice)
13028 *
13029 * Returns the minimun Effective Total Range.
13030 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013031static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013032xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013033{
13034 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013035 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013036 return (0);
13037 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013038 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013039 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013040 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013041
13042 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013043 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013044 while (part != NULL) {
13045 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13046 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013047 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013048 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013049 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013050 if (cur == 0)
13051 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013052 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013053 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013054 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013055 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013056 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013057 } else {
13058 /* <all> and <sequence> */
13059 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013060 xmlSchemaParticlePtr part =
13061 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013062
13063 if (part == NULL)
13064 return (0);
13065 do {
13066 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13067 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013068 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013069 else
13070 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013071 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013072 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013073 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013074 }
13075}
13076
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013077/**
13078 * xmlSchemaGetParticleTotalRangeMax:
13079 * @particle: the particle
13080 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013081 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013082 * (all and sequence) + (choice)
13083 *
13084 * Returns the maximum Effective Total Range.
13085 */
13086static int
13087xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13088{
13089 if ((particle->children == NULL) ||
13090 (particle->children->children == NULL))
13091 return (0);
13092 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13093 int max = -1, cur;
13094 xmlSchemaParticlePtr part =
13095 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013096
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013097 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13098 if (part->children == NULL)
13099 continue;
13100 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13101 (part->children->type == XML_SCHEMA_TYPE_ANY))
13102 cur = part->maxOccurs;
13103 else
13104 cur = xmlSchemaGetParticleTotalRangeMax(part);
13105 if (cur == UNBOUNDED)
13106 return (UNBOUNDED);
13107 if ((max < cur) || (max == -1))
13108 max = cur;
13109 }
13110 /* TODO: Handle overflows? */
13111 return (particle->maxOccurs * max);
13112 } else {
13113 /* <all> and <sequence> */
13114 int sum = 0, cur;
13115 xmlSchemaParticlePtr part =
13116 (xmlSchemaParticlePtr) particle->children->children;
13117
13118 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13119 if (part->children == NULL)
13120 continue;
13121 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13122 (part->children->type == XML_SCHEMA_TYPE_ANY))
13123 cur = part->maxOccurs;
13124 else
13125 cur = xmlSchemaGetParticleTotalRangeMax(part);
13126 if (cur == UNBOUNDED)
13127 return (UNBOUNDED);
13128 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13129 return (UNBOUNDED);
13130 sum += cur;
13131 }
13132 /* TODO: Handle overflows? */
13133 return (particle->maxOccurs * sum);
13134 }
13135}
13136
13137/**
13138 * xmlSchemaIsParticleEmptiable:
13139 * @particle: the particle
13140 *
13141 * Schema Component Constraint: Particle Emptiable
13142 * Checks whether the given particle is emptiable.
13143 *
13144 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013145 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013146static int
13147xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13148{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013149 /*
13150 * SPEC (1) "Its {min occurs} is 0."
13151 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013152 if ((particle == NULL) || (particle->minOccurs == 0) ||
13153 (particle->children == NULL))
13154 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013155 /*
13156 * SPEC (2) "Its {term} is a group and the minimum part of the
13157 * effective total range of that group, [...] is 0."
13158 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013159 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013160 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013161 return (1);
13162 }
13163 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013164}
13165
13166/**
13167 * xmlSchemaCheckCOSSTDerivedOK:
13168 * @type: the derived simple type definition
13169 * @baseType: the base type definition
13170 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013171 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013172 * Type Derivation OK (Simple) (cos-st-derived-OK)
13173 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013174 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013175 * derived from @baseType.
13176 *
13177 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013178 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013179static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013180xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13181 xmlSchemaTypePtr baseType,
13182 int subset)
13183{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013184 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013185 * 1 They are the same type definition.
13186 * TODO: The identy check might have to be more complex than this.
13187 */
13188 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013189 return (0);
13190 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013191 * 2.1 restriction is not in the subset, or in the {final}
13192 * of its own {base type definition};
13193 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013194 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013195 (xmlSchemaTypeFinalContains(type->baseType,
13196 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13197 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013198 }
13199 /* 2.2 */
13200 if (type->baseType == baseType) {
13201 /*
13202 * 2.2.1 D's ·base type definition· is B.
13203 */
13204 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013205 }
13206 /*
13207 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13208 * and is validly derived from B given the subset, as defined by this
13209 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013210 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013211 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013212 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013213 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013214 return (0);
13215 }
13216 /*
13217 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013218 * definition·.
13219 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013220 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013221 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013222 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013223 }
13224 /*
13225 * 2.2.4 B's {variety} is union and D is validly derived from a type
13226 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013227 * defined by this constraint.
13228 *
13229 * NOTE: This seems not to involve built-in types, since there is no
13230 * built-in Union Simple Type.
13231 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013232 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013233 xmlSchemaTypeLinkPtr cur;
13234
13235 cur = baseType->memberTypes;
13236 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013237 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013238 return (0);
13239 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013240 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013241 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013242
Daniel Veillard01fa6152004-06-29 17:04:39 +000013243 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13244}
13245
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013246/**
13247 * xmlSchemaCheckTypeDefCircularInternal:
13248 * @pctxt: the schema parser context
13249 * @ctxtType: the type definition
13250 * @ancestor: an ancestor of @ctxtType
13251 *
13252 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013253 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013254 *
13255 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13256 * circular, 0 otherwise.
13257 */
13258static int
13259xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13260 xmlSchemaTypePtr ctxtType,
13261 xmlSchemaTypePtr ancestor)
13262{
13263 int ret;
13264
13265 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13266 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013267
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013268 if (ctxtType == ancestor) {
13269 xmlSchemaPCustomErr(pctxt,
13270 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13271 NULL, ctxtType, GET_NODE(ctxtType),
13272 "The definition is circular", NULL);
13273 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13274 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013275 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13276 /*
13277 * Avoid inifinite recursion on circular types not yet checked.
13278 */
13279 return (0);
13280 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013281 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13282 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13283 ancestor->baseType);
13284 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13285 return (ret);
13286}
13287
13288/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013289 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013290 * @item: the complex/simple type definition
13291 * @ctxt: the parser context
13292 * @name: the name
13293 *
13294 * Checks for circular type definitions.
13295 */
13296static void
13297xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013298 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013299 const xmlChar * name ATTRIBUTE_UNUSED)
13300{
13301 if ((item == NULL) ||
13302 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13303 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13304 return;
13305 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13306
13307}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013308
13309/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013310 * xmlSchemaResolveTypeDefs:
13311 * @item: the complex/simple type definition
13312 * @ctxt: the parser context
13313 * @name: the name
13314 *
13315 * Checks for circular type definitions.
13316 */
13317static void
13318xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013319 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013320 const xmlChar * name ATTRIBUTE_UNUSED)
13321{
13322 if (typeDef == NULL)
13323 return;
13324
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013325 /*
13326 * Resolve the base type.
13327 */
13328 if (typeDef->baseType == NULL) {
13329 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13330 typeDef->base, typeDef->baseNs);
13331 if (typeDef->baseType == NULL) {
13332 xmlSchemaPResCompAttrErr(ctxt,
13333 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013334 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013335 "base", typeDef->base, typeDef->baseNs,
13336 XML_SCHEMA_TYPE_SIMPLE, NULL);
13337 return;
13338 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013339 }
13340 if (IS_SIMPLE_TYPE(typeDef)) {
13341 if (VARIETY_UNION(typeDef)) {
13342 /*
13343 * Resolve the memberTypes.
13344 */
13345 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13346 return;
13347 } else if (VARIETY_LIST(typeDef)) {
13348 /*
13349 * Resolve the itemType.
13350 */
13351 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13352 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13353 typeDef->ref, typeDef->refNs);
13354 if ((typeDef->subtypes == NULL) ||
13355 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13356 typeDef->subtypes = NULL;
13357 xmlSchemaPResCompAttrErr(ctxt,
13358 XML_SCHEMAP_SRC_RESOLVE,
13359 typeDef, typeDef->node,
13360 "itemType", typeDef->ref, typeDef->refNs,
13361 XML_SCHEMA_TYPE_SIMPLE, NULL);
13362 }
13363 }
13364 return;
13365 }
13366 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013367}
13368
13369
13370
13371/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013372 * xmlSchemaCheckSTPropsCorrect:
13373 * @ctxt: the schema parser context
13374 * @type: the simple type definition
13375 *
13376 * Checks st-props-correct.
13377 *
13378 * Returns 0 if the properties are correct,
13379 * if not, a positive error code and -1 on internal
13380 * errors.
13381 */
13382static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013383xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013384 xmlSchemaTypePtr type)
13385{
13386 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13387 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013388 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013389
Daniel Veillardc0826a72004-08-10 14:17:33 +000013390 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013391 /*
13392 * Schema Component Constraint: Simple Type Definition Properties Correct
13393 *
13394 * NOTE: This is somehow redundant, since we actually built a simple type
13395 * to have all the needed information; this acts as an self test.
13396 */
13397 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13398 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013399 /* Base type: If the datatype has been ·derived· by ·restriction·
13400 * then the Simple Type Definition component from which it is ·derived·,
13401 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013402 */
13403 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013404 /*
13405 * TODO: Think about: "modulo the impact of Missing
13406 * Sub-components (§5.3)."
13407 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013408 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013409 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013410 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013411 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013412 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013413
Daniel Veillard01fa6152004-06-29 17:04:39 +000013414 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013415 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013416 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013417 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013418 NULL, type, NULL,
13419 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013420 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013421 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013422 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13423 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013424 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13425 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13426 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013427 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013428 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013429 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013430 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013431 "the simple ur-type definition as base type, not '%s'",
13432 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013433 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013434 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13435 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013436 /*
13437 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013438 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013439 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13440 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013441 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013442 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013443 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013444 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013445 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13446 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013447 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013448
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013449 /*
13450 * 3 The {final} of the {base type definition} must not contain restriction.
13451 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013452 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013453 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13454 xmlSchemaPCustomErr(ctxt,
13455 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013456 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013457 "The 'final' of its base type '%s' must not contain "
13458 "'restriction'",
13459 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013460 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013461 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013462 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013463
13464 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013465 * 2 All simple type definitions must be derived ultimately from the ·simple
13466 * ur-type definition (so· circular definitions are disallowed). That is, it
13467 * must be possible to reach a built-in primitive datatype or the ·simple
13468 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013469 *
13470 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013471 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013472 return (0);
13473}
13474
13475/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013476 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013477 * @ctxt: the schema parser context
13478 * @type: the simple type definition
13479 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013480 * Schema Component Constraint:
13481 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13482
13483 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013484 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013485 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013486 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013487 * a positive error code otherwise.
13488 */
13489static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013491 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013492{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013493 xmlChar *str = NULL;
13494
Daniel Veillard01fa6152004-06-29 17:04:39 +000013495 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013496 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13497 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013498 return (-1);
13499 }
13500
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013501 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013502 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013503 /*
13504 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013505 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013506 */
13507 if (! VARIETY_ATOMIC(type->baseType)) {
13508 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013509 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013510 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013511 "The base type '%s' is not an atomic simple type",
13512 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013513 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013514 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13515 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013516 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013517 * restriction.
13518 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013519 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013520 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013521 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013522 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013523 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013524 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013525 "The final of its base type '%s' must not contain 'restriction'",
13526 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013527 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013528 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13529 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013530
13531 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013532 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013533 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013534 * Primitive datatypes.
13535 */
13536 if (type->facets != NULL) {
13537 xmlSchemaFacetPtr facet;
13538 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013539
Daniel Veillard01fa6152004-06-29 17:04:39 +000013540 primitive = xmlSchemaGetPrimitiveType(type);
13541 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013542 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13543 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013544 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013545 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013546 facet = type->facets;
13547 do {
13548 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013549 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013550 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013551 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013552 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013553 }
13554 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013555 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013556 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013557 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013558 }
13559 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013560 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13561 * of the {base type definition} (call this BF),then the DF's {value}
13562 * must be a valid restriction of BF's {value} as defined in
13563 * [XML Schemas: Datatypes]."
13564 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013565 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013566 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013567 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013568 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013569 xmlSchemaTypePtr itemType = NULL;
13570
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013571 itemType = type->subtypes;
13572 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013573 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13574 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013575 return (-1);
13576 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013577 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013578 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013579 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013580 * 2.1 The {item type definition} must have a {variety} of atomic or
13581 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013582 * must be atomic).
13583 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013584 if ((! VARIETY_ATOMIC(itemType)) &&
13585 (! VARIETY_UNION(itemType))) {
13586 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013587 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013588 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013589 "The item type '%s' does not have a variety of atomic or union",
13590 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013591 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013592 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013593 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013594 xmlSchemaTypeLinkPtr member;
13595
13596 member = itemType->memberTypes;
13597 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013598 if (! VARIETY_ATOMIC(member->type)) {
13599 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013600 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013601 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013602 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013603 "member type '%s' of this item type is not atomic",
13604 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013605 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013606 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13607 }
13608 member = member->next;
13609 }
13610 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013611
13612 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013613 xmlSchemaFacetPtr facet;
13614 /*
13615 * This is the case if we have: <simpleType><list ..
13616 */
13617 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013618 * 2.3.1
13619 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013620 * contain list.
13621 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013622 if (xmlSchemaTypeFinalContains(itemType,
13623 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13624 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013625 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013626 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013627 "The final of its item type '%s' must not contain 'list'",
13628 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013629 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013630 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13631 }
13632 /*
13633 * 2.3.1.2 The {facets} must only contain the whiteSpace
13634 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013635 * OPTIMIZE TODO: the S4S already disallows any facet
13636 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013637 */
13638 if (type->facets != NULL) {
13639 facet = type->facets;
13640 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013641 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013642 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013643 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013644 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013645 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13646 }
13647 facet = facet->next;
13648 } while (facet != NULL);
13649 }
13650 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013651 * MAYBE TODO: (Hmm, not really) Datatypes states:
13652 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13653 * whose ·lexical space· allows space (such as string or anyURI)or
13654 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013655 * ·lexical space· allows space.
13656 */
13657 } else {
13658 /*
13659 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013660 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013661 */
13662 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013663 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013664 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13665 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013666 if (! VARIETY_LIST(type->baseType)) {
13667 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013668 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013669 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013670 "The base type '%s' must be a list type",
13671 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013672 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013673 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13674 }
13675 /*
13676 * 2.3.2.2 The {final} of the {base type definition} must not
13677 * contain restriction.
13678 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013679 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013680 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013681 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013682 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013683 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013684 "The 'final' of the base type '%s' must not contain 'restriction'",
13685 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013686 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013687 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13688 }
13689 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013690 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013691 * from the {base type definition}'s {item type definition} given
13692 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13693 */
13694 {
13695 xmlSchemaTypePtr baseItemType;
13696
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013697 baseItemType = type->baseType->subtypes;
13698 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013699 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13700 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013701 return (-1);
13702 }
13703 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013704 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13705 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013706 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013707 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013708 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013709 NULL, type, NULL,
13710 "The item type '%s' is not validly derived from "
13711 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013712 xmlSchemaGetComponentQName(&str, itemType),
13713 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13714 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013715
13716 FREE_AND_NULL(str)
13717 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013718 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013719 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13720 }
13721 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013722
Daniel Veillard01fa6152004-06-29 17:04:39 +000013723 if (type->facets != NULL) {
13724 xmlSchemaFacetPtr facet;
13725 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013726 /*
13727 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013728 * and enumeration facet components are allowed among the {facets}.
13729 */
13730 facet = type->facets;
13731 do {
13732 switch (facet->type) {
13733 case XML_SCHEMA_FACET_LENGTH:
13734 case XML_SCHEMA_FACET_MINLENGTH:
13735 case XML_SCHEMA_FACET_MAXLENGTH:
13736 case XML_SCHEMA_FACET_WHITESPACE:
13737 /*
13738 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013739 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013740 */
13741 case XML_SCHEMA_FACET_PATTERN:
13742 case XML_SCHEMA_FACET_ENUMERATION:
13743 break;
13744 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013745 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013746 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013747 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013748 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013749 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013750 * invalid facets.
13751 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013752 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013753 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013754 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013755 facet = facet->next;
13756 } while (facet != NULL);
13757 if (ok == 0)
13758 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13759 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013760 * SPEC (2.3.2.5) (same as 1.3.2)
13761 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013762 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013763 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013764 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013765 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013766 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013767 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013768 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013769 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013770 * atomic or list.
13771 */
13772 xmlSchemaTypeLinkPtr member;
13773
13774 member = type->memberTypes;
13775 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013776 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013777 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013778
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013779 if ((! VARIETY_ATOMIC(member->type)) &&
13780 (! VARIETY_LIST(member->type))) {
13781 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013782 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013783 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013784 "The member type '%s' is neither an atomic, nor a list type",
13785 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013786 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013787 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13788 }
13789 member = member->next;
13790 }
13791 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013792 * 3.3.1 If the {base type definition} is the ·simple ur-type
13793 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013794 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013795 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013796 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013797 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013798 * {final} which does not contain union.
13799 */
13800 member = type->memberTypes;
13801 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013802 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013803 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013804 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013805 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013806 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013807 "The 'final' of member type '%s' contains 'union'",
13808 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013809 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013810 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13811 }
13812 member = member->next;
13813 }
13814 /*
13815 * 3.3.1.2 The {facets} must be empty.
13816 */
13817 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013818 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013819 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013820 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013821 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013822 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13823 }
13824 } else {
13825 /*
13826 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013827 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013828 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013829 if (! VARIETY_UNION(type->baseType)) {
13830 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013831 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013832 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013833 "The base type '%s' is not a union type",
13834 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013835 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013836 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13837 }
13838 /*
13839 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13840 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013841 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013842 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013843 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013844 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013845 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013846 "The 'final' of its base type '%s' must not contain 'restriction'",
13847 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013848 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013849 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13850 }
13851 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013852 * 3.3.2.3 The {member type definitions}, in order, must be validly
13853 * derived from the corresponding type definitions in the {base
13854 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013855 * as defined in Type Derivation OK (Simple) (§3.14.6).
13856 */
13857 {
13858 xmlSchemaTypeLinkPtr baseMember;
13859
13860 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013861 * OPTIMIZE: if the type is restricting, it has no local defined
13862 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013863 * thus a check for equality can be skipped.
13864 */
13865 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013866 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013867 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013868 * types of it's base type. This check seems not necessary with
13869 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013870 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013871 */
13872 if (type->memberTypes != NULL) {
13873 member = type->memberTypes;
13874 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013875 if ((member == NULL) && (baseMember != NULL)) {
13876 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13877 "different number of member types in base");
13878 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013879 while (member != NULL) {
13880 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013881 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13882 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013883 }
13884 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013885 (xmlSchemaCheckCOSSTDerivedOK(
13886 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013887 xmlChar *strBMT = NULL, *strBT = NULL;
13888
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013889 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013890 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13891 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013892 "The member type %s is not validly "
13893 "derived from its corresponding member "
13894 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013895 xmlSchemaGetComponentQName(&str, member->type),
13896 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13897 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013898 FREE_AND_NULL(str)
13899 FREE_AND_NULL(strBMT)
13900 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013901 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013902 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013903 member = member->next;
13904 baseMember = baseMember->next;
13905 }
13906 }
13907 }
13908 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013909 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013910 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013911 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013912 if (type->facets != NULL) {
13913 xmlSchemaFacetPtr facet;
13914 int ok = 1;
13915
13916 facet = type->facets;
13917 do {
13918 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13919 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013920 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013921 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013922 NULL, type, facet);
13923 ok = 0;
13924 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013925 facet = facet->next;
13926 } while (facet != NULL);
13927 if (ok == 0)
13928 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013929
Daniel Veillard01fa6152004-06-29 17:04:39 +000013930 }
13931 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013932 * SPEC (3.3.2.5) (same as 1.3.2)
13933 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013934 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013935 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013936 */
13937 }
13938 }
13939
13940 return (0);
13941}
13942
13943/**
13944 * xmlSchemaCheckSRCSimpleType:
13945 * @ctxt: the schema parser context
13946 * @type: the simple type definition
13947 *
13948 * Checks crc-simple-type constraints.
13949 *
13950 * Returns 0 if the constraints are satisfied,
13951 * if not a positive error code and -1 on internal
13952 * errors.
13953 */
13954static int
13955xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13956 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013957{
13958 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013959 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013960 * must satisfy the conditions set out in Constraints on Simple Type
13961 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013962 */
13963 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13964 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13965 /*
13966 * TODO: Removed this, since it got annoying to get an
13967 * extra error report, if anything failed until now.
13968 * Enable this if needed.
13969 */
13970 /*
13971 xmlSchemaPErr(ctxt, type->node,
13972 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013973 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013974 "on simple type definitions.\n",
13975 type->name, NULL);
13976 */
13977 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13978 }
13979
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013980 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013981 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013982 * src-simple-type.2 If the <restriction> alternative is chosen,
13983 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013984 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013985 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013986 /*
13987 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013988 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013989 */
13990 } else if (VARIETY_LIST(type)) {
13991 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13992 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013993 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013994 *
13995 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013996 */
13997 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013998 xmlSchemaTypeLinkPtr member;
13999 xmlSchemaTypePtr ancestor, anySimpleType;
14000
14001 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14002
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014003 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14004 * the <union> alternative is chosen, there must not be any entries
14005 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000014006 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014007 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014008 member = type->memberTypes;
14009 while (member != NULL) {
14010 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014011 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014012 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014013 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014014 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014015 NULL, type, NULL,
14016 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014017 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014018 }
14019 if (IS_NOT_TYPEFIXED(ancestor))
14020 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014021 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014022 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014023 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014024 * type as item type, which in turn has a list ST as member
14025 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000014026 * was not yet performed.
14027 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014028 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014029
Daniel Veillard01fa6152004-06-29 17:04:39 +000014030 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014031 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014032 member = member->next;
14033 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014034 }
14035
14036 return (0);
14037}
14038
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014039static int
14040xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14041{
14042 if (ctxt->vctxt == NULL) {
14043 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14044 if (ctxt->vctxt == NULL) {
14045 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014046 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014047 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014048 "failed to create a temp. validation context.\n",
14049 NULL, NULL);
14050 return (-1);
14051 }
14052 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014053 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014054 }
14055 return (0);
14056}
14057
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014058static int
14059xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14060 xmlNodePtr node,
14061 xmlSchemaTypePtr type,
14062 const xmlChar *value,
14063 xmlSchemaValPtr *retVal,
14064 int fireErrors,
14065 int normalize,
14066 int isNormalized);
14067
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014068/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014069 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014070 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014071 * @type: the simple type definition
14072 * @value: the default value
14073 * @node: an optional node (the holder of the value)
14074 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014075 * Schema Component Constraint: Element Default Valid (Immediate)
14076 * (cos-valid-default)
14077 * This will be used by the parser only. For the validator there's
14078 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014079 *
14080 * Returns 0 if the constraints are satisfied,
14081 * if not, a positive error code and -1 on internal
14082 * errors.
14083 */
14084static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014085xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14086 xmlNodePtr node,
14087 xmlSchemaTypePtr type,
14088 const xmlChar *value,
14089 xmlSchemaValPtr *val)
14090{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014091 int ret = 0;
14092
14093 /*
14094 * cos-valid-default:
14095 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014096 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014097 * definition the appropriate case among the following must be true:
14098 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014099 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014100 /*
14101 * Complex type.
14102 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014103 * SPEC (2.1) "its {content type} must be a simple type definition
14104 * or mixed."
14105 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014106 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014107 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014108 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014109 if ((! HAS_SIMPLE_CONTENT(type)) &&
14110 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14111 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014112 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014113 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014114 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014115 "For a string to be a valid default, the type definition "
14116 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014117 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014118 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14119 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014120 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014121 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014122 * 1 If the type definition is a simple type definition, then the string
14123 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014124 * Valid (§3.14.4).
14125 *
14126 * AND
14127 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014128 * 2.2.1 If the {content type} is a simple type definition, then the
14129 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014130 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014131 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014132 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014133 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14134 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014135 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014136 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14137 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014138 else
14139 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014140
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014141 if (ret < 0) {
14142 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14143 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014144 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014145
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014146 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014147}
14148
14149/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014150 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014151 * @ctxt: the schema parser context
14152 * @type: the complex type definition
14153 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014154 *.(4.6) Constraints on Complex Type Definition Schema Components
14155 * Schema Component Constraint:
14156 * Complex Type Definition Properties Correct (ct-props-correct)
14157 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014158 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014159 * Returns 0 if the constraints are satisfied, a positive
14160 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014161 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014162static int
14163xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14164 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014165{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014166 /*
14167 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14168 *
14169 * SPEC (1) "The values of the properties of a complex type definition must
14170 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014171 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014172 * Sub-components (§5.3)."
14173 */
14174 if ((type->baseType != NULL) &&
14175 (IS_SIMPLE_TYPE(type->baseType)) &&
14176 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14177 /*
14178 * SPEC (2) "If the {base type definition} is a simple type definition,
14179 * the {derivation method} must be extension."
14180 */
14181 xmlSchemaPCustomErr(pctxt,
14182 XML_SCHEMAP_SRC_CT_1,
14183 NULL, type, NULL,
14184 "If the base type is a simple type, the derivation method must be "
14185 "'extension'", NULL);
14186 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014187 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014188 /*
14189 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14190 * definition·. That is, it must be possible to reach the ·ur-type
14191 * definition by repeatedly following the {base type definition}."
14192 *
14193 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14194 *
14195 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014196 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014197 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14198 * must not have {type definition}s which are or are derived from ID."
14199 *
14200 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14201 */
14202 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014203}
14204
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014205static int
14206xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14207 xmlSchemaTypePtr typeB)
14208{
14209 /*
14210 * TODO: This should implement component-identity
14211 * in the future.
14212 */
14213 if ((typeA == NULL) || (typeB == NULL))
14214 return (0);
14215 return (typeA == typeB);
14216}
14217
14218/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014219 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014220 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014221 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014222 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014223 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014224 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014225 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014226 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14227 *
14228 * STATUS: completed
14229 *
14230 * Returns 0 if the constraints are satisfied, or 1
14231 * if not.
14232 */
14233static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014234xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014235 xmlSchemaTypePtr baseType,
14236 int set)
14237{
14238 int equal = xmlSchemaAreEqualTypes(type, baseType);
14239 /* TODO: Error codes. */
14240 /*
14241 * SPEC "For a complex type definition (call it D, for derived)
14242 * to be validly derived from a type definition (call this
14243 * B, for base) given a subset of {extension, restriction}
14244 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014245 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014246 if (! equal) {
14247 /*
14248 * SPEC (1) "If B and D are not the same type definition, then the
14249 * {derivation method} of D must not be in the subset."
14250 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014251 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014252 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014253 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014254 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014255 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014256 } else {
14257 /*
14258 * SPEC (2.1) "B and D must be the same type definition."
14259 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014260 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014261 }
14262 /*
14263 * SPEC (2.2) "B must be D's {base type definition}."
14264 */
14265 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014266 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014267 /*
14268 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14269 * definition·."
14270 */
14271 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014272 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014273
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014274 if (IS_COMPLEX_TYPE(type->baseType)) {
14275 /*
14276 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14277 * must be validly derived from B given the subset as defined by this
14278 * constraint."
14279 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014280 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014281 baseType, set));
14282 } else {
14283 /*
14284 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14285 * must be validly derived from B given the subset as defined in Type
14286 * Derivation OK (Simple) (§3.14.6).
14287 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014288 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14289 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014290}
14291
14292/**
14293 * xmlSchemaCheckCOSDerivedOK:
14294 * @type: the derived simple type definition
14295 * @baseType: the base type definition
14296 *
14297 * Calls:
14298 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014299 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014300 * Checks wheter @type can be validly derived from @baseType.
14301 *
14302 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014303 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014304static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014305xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014306 xmlSchemaTypePtr baseType,
14307 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014308{
14309 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014310 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014311 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014312 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014313}
14314
William M. Brack2f2a6632004-08-20 23:09:47 +000014315/**
14316 * xmlSchemaCheckCOSCTExtends:
14317 * @ctxt: the schema parser context
14318 * @type: the complex type definition
14319 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014320 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014321 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014322 * Derivation Valid (Extension) (cos-ct-extends)
14323 *
14324 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014325 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014326 * (1.5)
14327 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014328 *
14329 * Returns 0 if the constraints are satisfied, a positive
14330 * error code if not and -1 if an internal error occured.
14331 */
14332static int
14333xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14334 xmlSchemaTypePtr type)
14335{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014336 xmlSchemaTypePtr base = type->baseType;
14337 /*
14338 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14339 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014340 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014341 /*
14342 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014343 * then all of the following must be true:"
14344 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014345 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14346 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014347 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014348 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014349 */
14350 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14351 xmlSchemaPCustomErr(ctxt,
14352 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14353 NULL, type, NULL,
14354 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014355 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014356 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14357 }
14358 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014359 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014360 * uses}
14361 * of the complex type definition itself, that is, for every attribute
14362 * use in the {attribute uses} of the {base type definition}, there
14363 * must be an attribute use in the {attribute uses} of the complex
14364 * type definition itself whose {attribute declaration} has the same
14365 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014366 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014367 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014368 * NOTE (1.2): This will be already satisfied by the way the attribute
14369 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14370 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014371 */
14372
14373 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014374 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14375 * definition must also have one, and the base type definition's
14376 * {attribute wildcard}'s {namespace constraint} must be a subset
14377 * of the complex type definition's {attribute wildcard}'s {namespace
14378 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014379 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014380 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014381 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014382 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014383 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014384 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014385 if ((type->contentTypeDef != NULL) &&
14386 (type->contentTypeDef == base->contentTypeDef)) {
14387 /*
14388 * SPEC (1.4.1) "The {content type} of the {base type definition}
14389 * and the {content type} of the complex type definition itself
14390 * must be the same simple type definition"
14391 * PASS
14392 */
14393 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14394 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14395 /*
14396 * SPEC (1.4.2) "The {content type} of both the {base type
14397 * definition} and the complex type definition itself must
14398 * be empty."
14399 * PASS
14400 */
14401 } else {
14402 /*
14403 * SPEC (1.4.3) "All of the following must be true:"
14404 */
14405 if (type->subtypes == NULL) {
14406 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014407 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014408 * definition itself must specify a particle.
14409 */
14410 xmlSchemaPCustomErr(ctxt,
14411 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14412 NULL, type, NULL,
14413 "The content type must specify a particle", NULL);
14414 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14415 }
14416 /*
14417 * SPEC (1.4.3.2) "One of the following must be true:"
14418 */
14419 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14420 /*
14421 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14422 * definition} must be empty.
14423 * PASS
14424 */
14425 } else {
14426 /*
14427 * SPEC (1.4.3.2.2) "All of the following must be true:"
14428 */
14429 if ((type->contentType != base->contentType) ||
14430 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14431 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14432 /*
14433 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14434 * or both must be element-only."
14435 */
14436 xmlSchemaPCustomErr(ctxt,
14437 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14438 NULL, type, NULL,
14439 "The content type of both, the type and its base "
14440 "type, must either 'mixed' or 'element-only'", NULL);
14441 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014442 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014443 /*
14444 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14445 * complex type definition must be a ·valid extension·
14446 * of the {base type definition}'s particle, as defined
14447 * in Particle Valid (Extension) (§3.9.6)."
14448 *
14449 * NOTE that we won't check "Particle Valid (Extension)",
14450 * since it is ensured by the derivation process in
14451 * xmlSchemaTypeFixup(). We need to implement this when heading
14452 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014453 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014454 }
14455 /*
14456 * TODO (1.5)
14457 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014458 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014459 } else {
14460 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014461 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014462 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014463 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014464 if (type->contentTypeDef != base) {
14465 /*
14466 * SPEC (2.1) "The {content type} must be the same simple type
14467 * definition."
14468 */
14469 xmlSchemaPCustomErr(ctxt,
14470 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14471 NULL, type, NULL,
14472 "The content type must be the simple base type", NULL);
14473 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14474 }
14475 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14476 /*
14477 * SPEC (2.2) "The {final} of the {base type definition} must not
14478 * contain extension"
14479 * NOTE that this is the same as (1.1).
14480 */
14481 xmlSchemaPCustomErr(ctxt,
14482 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14483 NULL, type, NULL,
14484 "The 'final' of the base type definition "
14485 "contains 'extension'", NULL);
14486 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014487 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014488 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014489 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014490}
14491
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014492/**
14493 * xmlSchemaCheckDerivationOKRestriction:
14494 * @ctxt: the schema parser context
14495 * @type: the complex type definition
14496 *
14497 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014498 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014499 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14500 *
14501 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014502 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014503 * (5.4.2), (5.2.2.1)
14504 *
14505 * Returns 0 if the constraints are satisfied, a positive
14506 * error code if not and -1 if an internal error occured.
14507 */
14508static int
14509xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14510 xmlSchemaTypePtr type)
14511{
14512 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014513
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014514 /*
14515 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14516 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014517 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014518 base = type->baseType;
14519 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14520 /*
14521 * SPEC (1) "The {base type definition} must be a complex type
14522 * definition whose {final} does not contain restriction."
14523 */
14524 xmlSchemaPCustomErr(ctxt,
14525 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14526 NULL, type, NULL,
14527 "The 'final' of the base type definition "
14528 "contains 'restriction'", NULL);
14529 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14530 }
14531 /*
14532 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14533 *
14534 * SPEC (5) "One of the following must be true:"
14535 */
14536 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14537 /*
14538 * SPEC (5.1) "The {base type definition} must be the
14539 * ·ur-type definition·."
14540 * PASS
14541 */
14542 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14543 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14544 /*
14545 * SPEC (5.2.1) "The {content type} of the complex type definition
14546 * must be a simple type definition"
14547 *
14548 * SPEC (5.2.2) "One of the following must be true:"
14549 */
14550 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14551 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14552 /*
14553 * SPEC (5.2.2.1) "The {content type} of the {base type
14554 * definition} must be a simple type definition from which
14555 * the {content type} is validly derived given the empty
14556 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14557 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014558 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014559 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14560 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014561 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014562 /*
14563 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14564 * and have a particle which is ·emptiable· as defined in
14565 * Particle Emptiable (§3.9.6)."
14566 * PASS
14567 */
14568 } else {
14569 xmlSchemaPCustomErr(ctxt,
14570 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14571 NULL, type, NULL,
14572 "The content type of the base type must be either "
14573 "a simple type or 'mixed' and an emptiable particle", NULL);
14574 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14575 }
14576 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14577 /*
14578 * SPEC (5.3.1) "The {content type} of the complex type itself must
14579 * be empty"
14580 */
14581 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14582 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014583 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014584 * definition} must also be empty."
14585 * PASS
14586 */
14587 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14588 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14589 xmlSchemaIsParticleEmptiable(
14590 (xmlSchemaParticlePtr) base->subtypes)) {
14591 /*
14592 * SPEC (5.3.2.2) "The {content type} of the {base type
14593 * definition} must be elementOnly or mixed and have a particle
14594 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14595 * PASS
14596 */
14597 } else {
14598 xmlSchemaPCustomErr(ctxt,
14599 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14600 NULL, type, NULL,
14601 "The content type of the base type must be either "
14602 "empty or 'mixed' (or 'elements-only') and an emptiable "
14603 "particle", NULL);
14604 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14605 }
14606 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014607 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014608 /*
14609 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14610 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014611 */
14612 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14613 /*
14614 * SPEC (5.4.1.2) "The {content type} of the complex type
14615 * definition itself and of the {base type definition} must be
14616 * mixed"
14617 */
14618 xmlSchemaPCustomErr(ctxt,
14619 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14620 NULL, type, NULL,
14621 "If the content type is 'mixed', then the content type of the "
14622 "base type must also be 'mixed'", NULL);
14623 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14624 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014625 /*
14626 * SPEC (5.4.2) "The particle of the complex type definition itself
14627 * must be a ·valid restriction· of the particle of the {content
14628 * type} of the {base type definition} as defined in Particle Valid
14629 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014630 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014631 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014632 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014633 } else {
14634 xmlSchemaPCustomErr(ctxt,
14635 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14636 NULL, type, NULL,
14637 "The type is not a valid restriction of its base type", NULL);
14638 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14639 }
14640 return (0);
14641}
14642
14643/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014644 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014645 * @ctxt: the schema parser context
14646 * @type: the complex type definition
14647 *
14648 * (3.4.6) Constraints on Complex Type Definition Schema Components
14649 *
14650 * Returns 0 if the constraints are satisfied, a positive
14651 * error code if not and -1 if an internal error occured.
14652 */
14653static int
14654xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14655 xmlSchemaTypePtr type)
14656{
14657 int ret;
14658 /*
14659 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014660 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014661 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14662 if (ret != 0)
14663 return (ret);
14664 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14665 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14666 else
14667 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14668 return (ret);
14669}
14670
14671/**
14672 * xmlSchemaCheckSRCCT:
14673 * @ctxt: the schema parser context
14674 * @type: the complex type definition
14675 *
14676 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014677 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014678 * Complex Type Definition Representation OK (src-ct)
14679 *
14680 * Returns 0 if the constraints are satisfied, a positive
14681 * error code if not and -1 if an internal error occured.
14682 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014683static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014684xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014685 xmlSchemaTypePtr type)
14686{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014687 xmlSchemaTypePtr base;
14688 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014689
14690 /*
14691 * TODO: Adjust the error codes here, as I used
14692 * XML_SCHEMAP_SRC_CT_1 only yet.
14693 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014694 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014695 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014696 /*
14697 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014698 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014699 * must be a complex type definition;
14700 */
14701 if (! IS_COMPLEX_TYPE(base)) {
14702 xmlChar *str = NULL;
14703 xmlSchemaPCustomErr(ctxt,
14704 XML_SCHEMAP_SRC_CT_1,
14705 NULL, type, type->node,
14706 "If using <complexContent>, the base type is expected to be "
14707 "a complex type. The base type '%s' is a simple type",
14708 xmlSchemaFormatQName(&str, base->targetNamespace,
14709 base->name));
14710 FREE_AND_NULL(str)
14711 return (XML_SCHEMAP_SRC_CT_1);
14712 }
14713 } else {
14714 /*
14715 * SPEC
14716 * 2 If the <simpleContent> alternative is chosen, all of the
14717 * following must be true:
14718 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14719 * base [attribute] must be one of the following:
14720 */
14721 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014722 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014723 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14724 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014725 /*
14726 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014727 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014728 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014729 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014730 xmlSchemaPCustomErr(ctxt,
14731 XML_SCHEMAP_SRC_CT_1,
14732 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014733 "If using <simpleContent> and <restriction>, the base "
14734 "type must be a complex type. The base type '%s' is "
14735 "a simple type",
14736 xmlSchemaFormatQName(&str, base->targetNamespace,
14737 base->name));
14738 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014739 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014740 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014741 } else {
14742 /* Base type is a complex type. */
14743 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14744 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14745 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014746 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014747 * simple type definition;
14748 * PASS
14749 */
14750 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014751 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014752 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014753 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014754 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014755 type->name);
14756 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014757 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014758 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14759 (type->flags &
14760 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014761
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014762 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014763 * 2.1.2 only if the <restriction> alternative is also
14764 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014765 * is mixed and a particle emptiable.
14766 */
14767 if (! xmlSchemaIsParticleEmptiable(
14768 (xmlSchemaParticlePtr) base->subtypes)) {
14769 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014770 } else
14771 /*
14772 * Attention: at this point the <simpleType> child is in
14773 * ->contentTypeDef (put there during parsing).
14774 */
14775 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014776 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014777 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014778 * 2.2 If clause 2.1.2 above is satisfied, then there
14779 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014780 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014781 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014782 /* TODO: Change error code to ..._SRC_CT_2_2. */
14783 xmlSchemaPCustomErr(ctxt,
14784 XML_SCHEMAP_SRC_CT_1,
14785 NULL, type, NULL,
14786 "A <simpleType> is expected among the children "
14787 "of <restriction>, if <simpleContent> is used and "
14788 "the base type '%s' is a complex type",
14789 xmlSchemaFormatQName(&str, base->targetNamespace,
14790 base->name));
14791 FREE_AND_NULL(str)
14792 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014793 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014794 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014795 ret = XML_SCHEMAP_SRC_CT_1;
14796 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014797 }
14798 if (ret > 0) {
14799 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014800 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014801 xmlSchemaPCustomErr(ctxt,
14802 XML_SCHEMAP_SRC_CT_1,
14803 NULL, type, NULL,
14804 "If <simpleContent> and <restriction> is used, the "
14805 "base type must be a simple type or a complex type with "
14806 "mixed content and particle emptiable. The base type "
14807 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014808 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014809 base->name));
14810 } else {
14811 xmlSchemaPCustomErr(ctxt,
14812 XML_SCHEMAP_SRC_CT_1,
14813 NULL, type, NULL,
14814 "If <simpleContent> and <extension> is used, the "
14815 "base type must be a simple type. The base type '%s' "
14816 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014817 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014818 base->name));
14819 }
14820 FREE_AND_NULL(str)
14821 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014822 }
14823 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014824 * SPEC (3) "The corresponding complex type definition component must
14825 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014826 * Definition Schema Components (§3.4.6);"
14827 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014828 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014829 /*
14830 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014831 * above for {attribute wildcard} is satisfied, the intensional
14832 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014833 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014834 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014835 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014836 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014837}
William M. Brack2f2a6632004-08-20 23:09:47 +000014838
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014839#ifdef ENABLE_PARTICLE_RESTRICTION
14840/**
14841 * xmlSchemaCheckParticleRangeOK:
14842 * @ctxt: the schema parser context
14843 * @type: the complex type definition
14844 *
14845 * (3.9.6) Constraints on Particle Schema Components
14846 * Schema Component Constraint:
14847 * Occurrence Range OK (range-ok)
14848 *
14849 * STATUS: complete
14850 *
14851 * Returns 0 if the constraints are satisfied, a positive
14852 * error code if not and -1 if an internal error occured.
14853 */
14854static int
14855xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14856 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014857{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014858 if (rmin < bmin)
14859 return (1);
14860 if ((bmax != UNBOUNDED) &&
14861 (rmax > bmax))
14862 return (1);
14863 return (0);
14864}
14865
14866/**
14867 * xmlSchemaCheckRCaseNameAndTypeOK:
14868 * @ctxt: the schema parser context
14869 * @r: the restricting element declaration particle
14870 * @b: the base element declaration particle
14871 *
14872 * (3.9.6) Constraints on Particle Schema Components
14873 * Schema Component Constraint:
14874 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14875 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014876 *
14877 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014878 * MISSING (3.2.3)
14879 * CLARIFY: (3.2.2)
14880 *
14881 * Returns 0 if the constraints are satisfied, a positive
14882 * error code if not and -1 if an internal error occured.
14883 */
14884static int
14885xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14886 xmlSchemaParticlePtr r,
14887 xmlSchemaParticlePtr b)
14888{
14889 xmlSchemaElementPtr elemR, elemB;
14890
14891 /* TODO: Error codes (rcase-NameAndTypeOK). */
14892 elemR = (xmlSchemaElementPtr) r->children;
14893 elemB = (xmlSchemaElementPtr) b->children;
14894 /*
14895 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14896 * the same."
14897 */
14898 if ((elemR != elemB) &&
14899 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14900 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14901 return (1);
14902 /*
14903 * SPEC (2) "R's occurrence range is a valid restriction of B's
14904 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14905 */
14906 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14907 b->minOccurs, b->maxOccurs) != 0)
14908 return (1);
14909 /*
14910 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14911 * {scope} are global."
14912 */
14913 if (elemR == elemB)
14914 return (0);
14915 /*
14916 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14917 */
14918 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14919 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14920 return (1);
14921 /*
14922 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14923 * or is not fixed, or R's declaration's {value constraint} is fixed
14924 * with the same value."
14925 */
14926 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14927 ((elemR->value == NULL) ||
14928 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14929 /* TODO: Equality of the initial value or normalized or canonical? */
14930 (! xmlStrEqual(elemR->value, elemB->value))))
14931 return (1);
14932 /*
14933 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14934 * definitions} is a subset of B's declaration's {identity-constraint
14935 * definitions}, if any."
14936 */
14937 if (elemB->idcs != NULL) {
14938 /* TODO */
14939 }
14940 /*
14941 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14942 * superset of B's declaration's {disallowed substitutions}."
14943 */
14944 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14945 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14946 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14947 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14948 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14949 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14950 return (1);
14951 /*
14952 * SPEC (3.2.5) "R's {type definition} is validly derived given
14953 * {extension, list, union} from B's {type definition}"
14954 *
14955 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14956 * set, if the corresponding constraints handle "restriction" and
14957 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014958 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014959 */
14960 {
14961 int set = 0;
14962
14963 set |= SUBSET_EXTENSION;
14964 set |= SUBSET_LIST;
14965 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014966 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014967 elemB->subtypes, set) != 0)
14968 return (1);
14969 }
14970 return (0);
14971}
14972
14973/**
14974 * xmlSchemaCheckRCaseNSCompat:
14975 * @ctxt: the schema parser context
14976 * @r: the restricting element declaration particle
14977 * @b: the base wildcard particle
14978 *
14979 * (3.9.6) Constraints on Particle Schema Components
14980 * Schema Component Constraint:
14981 * Particle Derivation OK (Elt:Any -- NSCompat)
14982 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014983 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014984 * STATUS: complete
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
14990xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14991 xmlSchemaParticlePtr r,
14992 xmlSchemaParticlePtr b)
14993{
14994 /* TODO:Error codes (rcase-NSCompat). */
14995 /*
14996 * SPEC "For an element declaration particle to be a ·valid restriction·
14997 * of a wildcard particle all of the following must be true:"
14998 *
14999 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15000 * with respect to the wildcard's {namespace constraint} as defined by
15001 * Wildcard allows Namespace Name (§3.10.4)."
15002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015003 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015004 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15005 return (1);
15006 /*
15007 * SPEC (2) "R's occurrence range is a valid restriction of B's
15008 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15009 */
15010 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15011 b->minOccurs, b->maxOccurs) != 0)
15012 return (1);
15013
15014 return (0);
15015}
15016
15017/**
15018 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15019 * @ctxt: the schema parser context
15020 * @r: the restricting element declaration particle
15021 * @b: the base model group particle
15022 *
15023 * (3.9.6) Constraints on Particle Schema Components
15024 * Schema Component Constraint:
15025 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15026 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015027 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015028 * STATUS: TODO
15029 *
15030 * Returns 0 if the constraints are satisfied, a positive
15031 * error code if not and -1 if an internal error occured.
15032 */
15033static int
15034xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15035 xmlSchemaParticlePtr r,
15036 xmlSchemaParticlePtr b)
15037{
15038 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15039 TODO
15040 return (0);
15041}
15042
15043/**
15044 * xmlSchemaCheckRCaseNSSubset:
15045 * @ctxt: the schema parser context
15046 * @r: the restricting wildcard particle
15047 * @b: the base wildcard particle
15048 *
15049 * (3.9.6) Constraints on Particle Schema Components
15050 * Schema Component Constraint:
15051 * Particle Derivation OK (Any:Any -- NSSubset)
15052 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015053 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015054 * STATUS: complete
15055 *
15056 * Returns 0 if the constraints are satisfied, a positive
15057 * error code if not and -1 if an internal error occured.
15058 */
15059static int
15060xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15061 xmlSchemaParticlePtr r,
15062 xmlSchemaParticlePtr b,
15063 int isAnyTypeBase)
15064{
15065 /* TODO: Error codes (rcase-NSSubset). */
15066 /*
15067 * SPEC (1) "R's occurrence range is a valid restriction of B's
15068 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15069 */
15070 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15071 b->minOccurs, b->maxOccurs))
15072 return (1);
15073 /*
15074 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15075 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15076 */
15077 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15078 (xmlSchemaWildcardPtr) b->children))
15079 return (1);
15080 /*
15081 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15082 * definition·, R's {process contents} must be identical to or stronger
15083 * than B's {process contents}, where strict is stronger than lax is
15084 * stronger than skip."
15085 */
15086 if (! isAnyTypeBase) {
15087 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15088 ((xmlSchemaWildcardPtr) b->children)->processContents)
15089 return (1);
15090 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015091
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015092 return (0);
15093}
15094
15095/**
15096 * xmlSchemaCheckCOSParticleRestrict:
15097 * @ctxt: the schema parser context
15098 * @type: the complex type definition
15099 *
15100 * (3.9.6) Constraints on Particle Schema Components
15101 * Schema Component Constraint:
15102 * Particle Valid (Restriction) (cos-particle-restrict)
15103 *
15104 * STATUS: TODO
15105 *
15106 * Returns 0 if the constraints are satisfied, a positive
15107 * error code if not and -1 if an internal error occured.
15108 */
15109static int
15110xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15111 xmlSchemaParticlePtr r,
15112 xmlSchemaParticlePtr b)
15113{
15114 int ret = 0;
15115
15116 /*part = GET_PARTICLE(type);
15117 basePart = GET_PARTICLE(base);
15118 */
15119
15120 TODO
15121
15122 /*
15123 * SPEC (1) "They are the same particle."
15124 */
15125 if (r == b)
15126 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015127
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015128
15129 return (0);
15130}
15131
15132/**
15133 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15134 * @ctxt: the schema parser context
15135 * @r: the model group particle
15136 * @b: the base wildcard particle
15137 *
15138 * (3.9.6) Constraints on Particle Schema Components
15139 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015140 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015141 * NSRecurseCheckCardinality)
15142 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015143 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015144 * STATUS: TODO: subst-groups
15145 *
15146 * Returns 0 if the constraints are satisfied, a positive
15147 * error code if not and -1 if an internal error occured.
15148 */
15149static int
15150xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15151 xmlSchemaParticlePtr r,
15152 xmlSchemaParticlePtr b)
15153{
15154 xmlSchemaParticlePtr part;
15155 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15156 if ((r->children == NULL) || (r->children->children == NULL))
15157 return (-1);
15158 /*
15159 * SPEC "For a group particle to be a ·valid restriction· of a
15160 * wildcard particle..."
15161 *
15162 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015163 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015164 * Particle Valid (Restriction) (§3.9.6)."
15165 */
15166 part = (xmlSchemaParticlePtr) r->children->children;
15167 do {
15168 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15169 return (1);
15170 part = (xmlSchemaParticlePtr) part->next;
15171 } while (part != NULL);
15172 /*
15173 * SPEC (2) "The effective total range of the group [...] is a
15174 * valid restriction of B's occurrence range as defined by
15175 * Occurrence Range OK (§3.9.6)."
15176 */
15177 if (xmlSchemaCheckParticleRangeOK(
15178 xmlSchemaGetParticleTotalRangeMin(r),
15179 xmlSchemaGetParticleTotalRangeMax(r),
15180 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015181 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015182 return (0);
15183}
15184
15185/**
15186 * xmlSchemaCheckRCaseRecurse:
15187 * @ctxt: the schema parser context
15188 * @r: the <all> or <sequence> model group particle
15189 * @b: the base <all> or <sequence> model group particle
15190 *
15191 * (3.9.6) Constraints on Particle Schema Components
15192 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015193 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015194 Recurse)
15195 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015196 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015197 * STATUS: ?
15198 * TODO: subst-groups
15199 *
15200 * Returns 0 if the constraints are satisfied, a positive
15201 * error code if not and -1 if an internal error occured.
15202 */
15203static int
15204xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15205 xmlSchemaParticlePtr r,
15206 xmlSchemaParticlePtr b)
15207{
15208 /* xmlSchemaParticlePtr part; */
15209 /* TODO: Error codes (rcase-Recurse). */
15210 if ((r->children == NULL) || (b->children == NULL) ||
15211 (r->children->type != b->children->type))
15212 return (-1);
15213 /*
15214 * SPEC "For an all or sequence group particle to be a ·valid
15215 * restriction· of another group particle with the same {compositor}..."
15216 *
15217 * SPEC (1) "R's occurrence range is a valid restriction of B's
15218 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15219 */
15220 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15221 b->minOccurs, b->maxOccurs))
15222 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015223
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015224
15225 return (0);
15226}
15227
15228#endif
15229
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015230#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15231 xmlSchemaPCustomErrExt(pctxt, \
15232 XML_SCHEMAP_INVALID_FACET_VALUE, \
15233 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15234 "It is an error for both '%s' and '%s' to be specified on the "\
15235 "same type definition", \
15236 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15237 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15238
15239#define FACET_RESTR_ERR(fac1, msg) \
15240 xmlSchemaPCustomErr(pctxt, \
15241 XML_SCHEMAP_INVALID_FACET_VALUE, \
15242 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015243 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015244
15245#define FACET_RESTR_FIXED_ERR(fac) \
15246 xmlSchemaPCustomErr(pctxt, \
15247 XML_SCHEMAP_INVALID_FACET_VALUE, \
15248 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15249 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015250 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015251
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015252static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015253xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15254 xmlSchemaFacetPtr facet1,
15255 xmlSchemaFacetPtr facet2,
15256 int lessGreater,
15257 int orEqual,
15258 int ofBase)
15259{
15260 xmlChar *msg = NULL;
15261
15262 msg = xmlStrdup(BAD_CAST "'");
15263 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15264 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15265 if (lessGreater == 0)
15266 msg = xmlStrcat(msg, BAD_CAST " equal to");
15267 if (lessGreater == 1)
15268 msg = xmlStrcat(msg, BAD_CAST " greater than");
15269 else
15270 msg = xmlStrcat(msg, BAD_CAST " less than");
15271
15272 if (orEqual)
15273 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15274 msg = xmlStrcat(msg, BAD_CAST " '");
15275 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15276 if (ofBase)
15277 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15278 else
15279 msg = xmlStrcat(msg, BAD_CAST "'");
15280
15281 xmlSchemaPCustomErr(pctxt,
15282 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015283 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015284 (const char *) msg, NULL);
15285
15286 if (msg != NULL)
15287 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015288}
15289
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015290static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015291xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15292 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015293{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015294 xmlSchemaTypePtr base = type->baseType;
15295 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015296 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015297 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15298 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15299 fmininc = NULL, fmaxinc = NULL,
15300 fminexc = NULL, fmaxexc = NULL,
15301 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15302 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15303 bfmininc = NULL, bfmaxinc = NULL,
15304 bfminexc = NULL, bfmaxexc = NULL;
15305 int res, err = 0, fixedErr;
15306 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015307 * 3 The {facets} of R are the union of S and the {facets}
15308 * of B, eliminating duplicates. To eliminate duplicates,
15309 * when a facet of the same kind occurs in both S and the
15310 * {facets} of B, the one in the {facets} of B is not
15311 * included, with the exception of enumeration and pattern
15312 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015313 * are allowed.
15314 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015315
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015316 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15317 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015318
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015319 last = type->facetSet;
15320 if (last != NULL)
15321 while (last->next != NULL)
15322 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015323
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015324 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15325 facet = cur->facet;
15326 switch (facet->type) {
15327 case XML_SCHEMA_FACET_LENGTH:
15328 flength = facet; break;
15329 case XML_SCHEMA_FACET_MINLENGTH:
15330 fminlen = facet; break;
15331 case XML_SCHEMA_FACET_MININCLUSIVE:
15332 fmininc = facet; break;
15333 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15334 fminexc = facet; break;
15335 case XML_SCHEMA_FACET_MAXLENGTH:
15336 fmaxlen = facet; break;
15337 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15338 fmaxinc = facet; break;
15339 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15340 fmaxexc = facet; break;
15341 case XML_SCHEMA_FACET_TOTALDIGITS:
15342 ftotdig = facet; break;
15343 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15344 ffracdig = facet; break;
15345 default:
15346 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015347 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015348 }
15349 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15350 facet = cur->facet;
15351 switch (facet->type) {
15352 case XML_SCHEMA_FACET_LENGTH:
15353 bflength = facet; break;
15354 case XML_SCHEMA_FACET_MINLENGTH:
15355 bfminlen = facet; break;
15356 case XML_SCHEMA_FACET_MININCLUSIVE:
15357 bfmininc = facet; break;
15358 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15359 bfminexc = facet; break;
15360 case XML_SCHEMA_FACET_MAXLENGTH:
15361 bfmaxlen = facet; break;
15362 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15363 bfmaxinc = facet; break;
15364 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15365 bfmaxexc = facet; break;
15366 case XML_SCHEMA_FACET_TOTALDIGITS:
15367 bftotdig = facet; break;
15368 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15369 bffracdig = facet; break;
15370 default:
15371 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015372 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015373 }
15374 err = 0;
15375 /*
15376 * length and minLength or maxLength (2.2) + (3.2)
15377 */
15378 if (flength && (fminlen || fmaxlen)) {
15379 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15380 "either of 'minLength' or 'maxLength' to be specified on "
15381 "the same type definition")
15382 }
15383 /*
15384 * Mutual exclusions in the same derivation step.
15385 */
15386 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015387 /*
15388 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015389 */
15390 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15391 }
15392 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015393 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015394 * SCC "minInclusive and minExclusive"
15395 */
15396 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015397 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015398
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015399 if (flength && bflength) {
15400 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015401 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015402 * The values have to be equal.
15403 */
15404 res = xmlSchemaCompareValues(flength->val, bflength->val);
15405 if (res == -2)
15406 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015407 if (res != 0)
15408 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15409 if ((res != 0) && (bflength->fixed)) {
15410 FACET_RESTR_FIXED_ERR(flength)
15411 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015412
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015413 }
15414 if (fminlen && bfminlen) {
15415 /*
15416 * SCC "minLength valid restriction"
15417 * minLength >= BASE minLength
15418 */
15419 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15420 if (res == -2)
15421 goto internal_error;
15422 if (res == -1)
15423 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15424 if ((res != 0) && (bfminlen->fixed)) {
15425 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015426 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015427 }
15428 if (fmaxlen && bfmaxlen) {
15429 /*
15430 * SCC "maxLength valid restriction"
15431 * maxLength <= BASE minLength
15432 */
15433 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15434 if (res == -2)
15435 goto internal_error;
15436 if (res == 1)
15437 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15438 if ((res != 0) && (bfmaxlen->fixed)) {
15439 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015440 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015441 }
15442 /*
15443 * SCC "length and minLength or maxLength"
15444 */
15445 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015446 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015447 if (flength) {
15448 if (! fminlen)
15449 flength = bflength;
15450 if (fminlen) {
15451 /* (1.1) length >= minLength */
15452 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15453 if (res == -2)
15454 goto internal_error;
15455 if (res == -1)
15456 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15457 }
15458 if (! fmaxlen)
15459 fmaxlen = bfmaxlen;
15460 if (fmaxlen) {
15461 /* (2.1) length <= maxLength */
15462 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15463 if (res == -2)
15464 goto internal_error;
15465 if (res == 1)
15466 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15467 }
15468 }
15469 if (fmaxinc) {
15470 /*
15471 * "maxInclusive"
15472 */
15473 if (fmininc) {
15474 /* SCC "maxInclusive >= minInclusive" */
15475 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15476 if (res == -2)
15477 goto internal_error;
15478 if (res == -1) {
15479 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15480 }
15481 }
15482 /*
15483 * SCC "maxInclusive valid restriction"
15484 */
15485 if (bfmaxinc) {
15486 /* maxInclusive <= BASE maxInclusive */
15487 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15488 if (res == -2)
15489 goto internal_error;
15490 if (res == 1)
15491 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15492 if ((res != 0) && (bfmaxinc->fixed)) {
15493 FACET_RESTR_FIXED_ERR(fmaxinc)
15494 }
15495 }
15496 if (bfmaxexc) {
15497 /* maxInclusive < BASE maxExclusive */
15498 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15499 if (res == -2)
15500 goto internal_error;
15501 if (res != -1) {
15502 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15503 }
15504 }
15505 if (bfmininc) {
15506 /* maxInclusive >= BASE minInclusive */
15507 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15508 if (res == -2)
15509 goto internal_error;
15510 if (res == -1) {
15511 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15512 }
15513 }
15514 if (bfminexc) {
15515 /* maxInclusive > BASE minExclusive */
15516 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15517 if (res == -2)
15518 goto internal_error;
15519 if (res != 1) {
15520 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15521 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015522 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015523 }
15524 if (fmaxexc) {
15525 /*
15526 * "maxExclusive >= minExclusive"
15527 */
15528 if (fminexc) {
15529 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15530 if (res == -2)
15531 goto internal_error;
15532 if (res == -1) {
15533 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15534 }
15535 }
15536 /*
15537 * "maxExclusive valid restriction"
15538 */
15539 if (bfmaxexc) {
15540 /* maxExclusive <= BASE maxExclusive */
15541 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15542 if (res == -2)
15543 goto internal_error;
15544 if (res == 1) {
15545 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15546 }
15547 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015548 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015549 }
15550 }
15551 if (bfmaxinc) {
15552 /* maxExclusive <= BASE maxInclusive */
15553 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15554 if (res == -2)
15555 goto internal_error;
15556 if (res == 1) {
15557 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15558 }
15559 }
15560 if (bfmininc) {
15561 /* maxExclusive > BASE minInclusive */
15562 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15563 if (res == -2)
15564 goto internal_error;
15565 if (res != 1) {
15566 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15567 }
15568 }
15569 if (bfminexc) {
15570 /* maxExclusive > BASE minExclusive */
15571 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15572 if (res == -2)
15573 goto internal_error;
15574 if (res != 1) {
15575 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15576 }
15577 }
15578 }
15579 if (fminexc) {
15580 /*
15581 * "minExclusive < maxInclusive"
15582 */
15583 if (fmaxinc) {
15584 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15585 if (res == -2)
15586 goto internal_error;
15587 if (res != -1) {
15588 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15589 }
15590 }
15591 /*
15592 * "minExclusive valid restriction"
15593 */
15594 if (bfminexc) {
15595 /* minExclusive >= BASE minExclusive */
15596 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15597 if (res == -2)
15598 goto internal_error;
15599 if (res == -1) {
15600 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15601 }
15602 if ((res != 0) && (bfminexc->fixed)) {
15603 FACET_RESTR_FIXED_ERR(fminexc)
15604 }
15605 }
15606 if (bfmaxinc) {
15607 /* minExclusive <= BASE maxInclusive */
15608 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15609 if (res == -2)
15610 goto internal_error;
15611 if (res == 1) {
15612 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15613 }
15614 }
15615 if (bfmininc) {
15616 /* minExclusive >= BASE minInclusive */
15617 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15618 if (res == -2)
15619 goto internal_error;
15620 if (res == -1) {
15621 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15622 }
15623 }
15624 if (bfmaxexc) {
15625 /* minExclusive < BASE maxExclusive */
15626 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15627 if (res == -2)
15628 goto internal_error;
15629 if (res != -1) {
15630 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15631 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015632 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015633 }
15634 if (fmininc) {
15635 /*
15636 * "minInclusive < maxExclusive"
15637 */
15638 if (fmaxexc) {
15639 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15640 if (res == -2)
15641 goto internal_error;
15642 if (res != -1) {
15643 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15644 }
15645 }
15646 /*
15647 * "minExclusive valid restriction"
15648 */
15649 if (bfmininc) {
15650 /* minInclusive >= BASE minInclusive */
15651 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15652 if (res == -2)
15653 goto internal_error;
15654 if (res == -1) {
15655 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15656 }
15657 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015658 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015659 }
15660 }
15661 if (bfmaxinc) {
15662 /* minInclusive <= BASE maxInclusive */
15663 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15664 if (res == -2)
15665 goto internal_error;
15666 if (res == -1) {
15667 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15668 }
15669 }
15670 if (bfminexc) {
15671 /* minInclusive > BASE minExclusive */
15672 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15673 if (res == -2)
15674 goto internal_error;
15675 if (res != 1)
15676 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15677 }
15678 if (bfmaxexc) {
15679 /* minInclusive < BASE maxExclusive */
15680 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15681 if (res == -2)
15682 goto internal_error;
15683 if (res != -1)
15684 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15685 }
15686 }
15687 if (ftotdig && bftotdig) {
15688 /*
15689 * SCC " totalDigits valid restriction"
15690 * totalDigits <= BASE totalDigits
15691 */
15692 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15693 if (res == -2)
15694 goto internal_error;
15695 if (res == 1)
15696 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15697 -1, 1, 1);
15698 if ((res != 0) && (bftotdig->fixed)) {
15699 FACET_RESTR_FIXED_ERR(ftotdig)
15700 }
15701 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015702 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015703 /*
15704 * SCC "fractionDigits valid restriction"
15705 * fractionDigits <= BASE fractionDigits
15706 */
15707 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15708 if (res == -2)
15709 goto internal_error;
15710 if (res == 1)
15711 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15712 -1, 1, 1);
15713 if ((res != 0) && (bffracdig->fixed)) {
15714 FACET_RESTR_FIXED_ERR(ffracdig)
15715 }
15716 }
15717 /*
15718 * SCC "fractionDigits less than or equal to totalDigits"
15719 */
15720 if (! ftotdig)
15721 ftotdig = bftotdig;
15722 if (! ffracdig)
15723 ffracdig = bffracdig;
15724 if (ftotdig && ffracdig) {
15725 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15726 if (res == -2)
15727 goto internal_error;
15728 if (res == 1)
15729 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15730 -1, 1, 0);
15731 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015732 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015733 * *Enumerations* won' be added here, since only the first set
15734 * of enumerations in the ancestor-or-self axis is used
15735 * for validation, plus we need to use the base type of those
15736 * enumerations for whitespace.
15737 *
15738 * *Patterns*: won't be add here, since they are ORed at
15739 * type level and ANDed at ancestor level. This will
15740 * happed during validation by walking the base axis
15741 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015742 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015743 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15744 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015745 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015746 * Special handling of enumerations and patterns.
15747 * TODO: hmm, they should not appear in the set, so remove this.
15748 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015749 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015750 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015751 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015752 /*
15753 * Search for a duplicate facet in the current type.
15754 */
15755 link = type->facetSet;
15756 err = 0;
15757 fixedErr = 0;
15758 while (link != NULL) {
15759 facet = link->facet;
15760 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015761 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015762 case XML_SCHEMA_FACET_WHITESPACE:
15763 /*
15764 * The whitespace must be stronger.
15765 */
15766 if (facet->whitespace < bfacet->whitespace) {
15767 FACET_RESTR_ERR(flength,
15768 "The 'whitespace' value has to be equal to "
15769 "or stronger than the 'whitespace' value of "
15770 "the base type")
15771 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015772 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015773 (facet->whitespace != bfacet->whitespace)) {
15774 FACET_RESTR_FIXED_ERR(facet)
15775 }
15776 break;
15777 default:
15778 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015779 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015780 /* Duplicate found. */
15781 break;
15782 }
15783 link = link->next;
15784 }
15785 /*
15786 * If no duplicate was found: add the base types's facet
15787 * to the set.
15788 */
15789 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015790 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015791 xmlMalloc(sizeof(xmlSchemaFacetLink));
15792 if (link == NULL) {
15793 xmlSchemaPErrMemory(pctxt,
15794 "deriving facets, creating a facet link", NULL);
15795 return (-1);
15796 }
15797 link->facet = cur->facet;
15798 link->next = NULL;
15799 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015800 type->facetSet = link;
15801 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015802 last->next = link;
15803 last = link;
15804 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015805
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015806 }
15807
15808 return (0);
15809internal_error:
15810 xmlSchemaPCustomErr(pctxt,
15811 XML_SCHEMAP_INVALID_FACET_VALUE,
15812 NULL, type, NULL,
15813 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15814 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015815}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015816
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015817static int
15818xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15819 xmlSchemaTypePtr type)
15820{
15821 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15822 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015823 * The actual value is then formed by replacing any union type
15824 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015825 * {member type definitions}, in order.
15826 */
15827 link = type->memberTypes;
15828 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015829
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015830 if (IS_NOT_TYPEFIXED(link->type))
15831 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15832
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015833 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015834 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015835 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015836 link->type = subLink->type;
15837 if (subLink->next != NULL) {
15838 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015839 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015840 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015841 while (subLink != NULL) {
15842 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015843 xmlMalloc(sizeof(xmlSchemaTypeLink));
15844 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015845 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015846 NULL);
15847 return (-1);
15848 }
15849 newLink->type = subLink->type;
15850 prevLink->next = newLink;
15851 prevLink = newLink;
15852 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015853
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015854 subLink = subLink->next;
15855 }
15856 }
15857 }
15858 }
15859 link = link->next;
15860 }
15861 return (0);
15862}
15863
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015864static void
15865xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15866{
15867 int has = 0, needVal = 0, normVal = 0;
15868
15869 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15870 if (has) {
15871 needVal = (type->baseType->flags &
15872 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15873 normVal = (type->baseType->flags &
15874 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15875 }
15876 if (type->facets != NULL) {
15877 xmlSchemaFacetPtr fac;
15878
15879 for (fac = type->facets; fac != NULL; fac = fac->next) {
15880 switch (fac->type) {
15881 case XML_SCHEMA_FACET_WHITESPACE:
15882 break;
15883 case XML_SCHEMA_FACET_PATTERN:
15884 normVal = 1;
15885 has = 1;
15886 break;
15887 case XML_SCHEMA_FACET_ENUMERATION:
15888 needVal = 1;
15889 normVal = 1;
15890 has = 1;
15891 break;
15892 default:
15893 has = 1;
15894 break;
15895 }
15896 }
15897 }
15898 if (normVal)
15899 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15900 if (needVal)
15901 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15902 if (has)
15903 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15904
15905 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15906 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15907 /*
15908 * OPTIMIZE VAL TODO: Some facets need a computed value.
15909 */
15910 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15911 (prim->builtInType != XML_SCHEMAS_STRING)) {
15912 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15913 }
15914 }
15915}
15916
15917static int
15918xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15919{
15920
15921
15922 /*
15923 * Evaluate the whitespace-facet value.
15924 */
15925 if (VARIETY_LIST(type)) {
15926 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15927 return (0);
15928 } else if (VARIETY_UNION(type))
15929 return (0);
15930
15931 if (type->facetSet != NULL) {
15932 xmlSchemaFacetLinkPtr lin;
15933
15934 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15935 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15936 switch (lin->facet->whitespace) {
15937 case XML_SCHEMAS_FACET_PRESERVE:
15938 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15939 break;
15940 case XML_SCHEMAS_FACET_REPLACE:
15941 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15942 break;
15943 case XML_SCHEMAS_FACET_COLLAPSE:
15944 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15945 break;
15946 default:
15947 return (-1);
15948 }
15949 return (0);
15950 }
15951 }
15952 }
15953 /*
15954 * For all ·atomic· datatypes other than string (and types ·derived·
15955 * by ·restriction· from it) the value of whiteSpace is fixed to
15956 * collapse
15957 */
15958 {
15959 xmlSchemaTypePtr anc;
15960
15961 for (anc = type->baseType; anc != NULL &&
15962 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15963 anc = anc->baseType) {
15964
15965 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15966 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15967 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15968
15969 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15970 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15971 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15972
15973 } else
15974 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15975 break;
15976 }
15977 }
15978 return (0);
15979 }
15980 return (0);
15981}
15982
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015983/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015984 * xmlSchemaTypeFixup:
15985 * @typeDecl: the schema type definition
15986 * @ctxt: the schema parser context
15987 *
15988 * Fixes the content model of the type.
15989 */
15990static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015991xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015992 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015993{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015994 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015995 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015996 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15997 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015998 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015999 if (! IS_NOT_TYPEFIXED(type))
16000 return;
16001 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016002 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016003 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016004
16005 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016006 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016007 XML_SCHEMAP_INTERNAL,
16008 NULL, type, NULL,
16009 "Internal error: xmlSchemaTypeFixup, "
16010 "baseType is missing on '%s'", type->name);
16011 return;
16012 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016013
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016014 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016015 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016016
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016017 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016018 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016019 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016020 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016021 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016022 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16023 /*
16024 * Skip fixup if the base type is invalid.
16025 * TODO: Generate a warning!
16026 */
16027 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016028 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016029 /*
16030 * This basically checks if the base type can be derived.
16031 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016032 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016033 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16034 return;
16035 }
16036 /*
16037 * Fixup the content type.
16038 */
16039 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16040 /*
16041 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016042 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016043 if ((IS_COMPLEX_TYPE(baseType)) &&
16044 (baseType->contentTypeDef != NULL) &&
16045 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016046 xmlSchemaTypePtr contentBase, content;
16047 char buf[30];
16048 const xmlChar *tmpname;
16049 /*
16050 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016051 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016052 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016053 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016054 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016055 * SPEC (1.1) "the simple type definition corresponding to the
16056 * <simpleType> among the [children] of <restriction> if there
16057 * is one;"
16058 * Note that this "<simpleType> among the [children]" was put
16059 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016060 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016061 contentBase = type->contentTypeDef;
16062 type->contentTypeDef = NULL;
16063 } else {
16064 /*
16065 * (1.2) "...otherwise (<restriction> has no <simpleType>
16066 * among its [children]), the simple type definition which
16067 * is the {content type} of the ... base type."
16068 */
16069 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016070 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016071 /*
16072 * SPEC
16073 * "... a simple type definition which restricts the simple
16074 * type definition identified in clause 1.1 or clause 1.2
16075 * with a set of facet components"
16076 *
16077 * Create the anonymous simple type, which will be the content
16078 * type of the complex type.
16079 */
16080 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16081 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16082 content = xmlSchemaAddType(pctxt,
16083 pctxt->schema, tmpname, tmpname, type->node);
16084 if (content == NULL)
16085 return;
16086 /*
16087 * We will use the same node as for the <complexType>
16088 * to have it somehow anchored in the schema doc.
16089 */
16090 content->node = type->node;
16091 content->type = XML_SCHEMA_TYPE_SIMPLE;
16092 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16093 content->baseType = contentBase;
16094 /*
16095 * Move the facets, previously anchored on the complexType.
16096 */
16097 content->facets = type->facets;
16098 type->facets = NULL;
16099 content->facetSet = type->facetSet;
16100 type->facetSet = NULL;
16101
16102 type->contentTypeDef = content;
16103 if (IS_NOT_TYPEFIXED(contentBase))
16104 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16105 xmlSchemaTypeFixup(content, pctxt, NULL);
16106
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016107 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16108 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16109 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16110 /*
16111 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16112 * an emptiable particle, then a simple type definition which
16113 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016114 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016115 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016116 (type->contentTypeDef->baseType == NULL)) {
16117 /*
16118 * TODO: Check if this ever happens.
16119 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016120 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016121 XML_SCHEMAP_INTERNAL,
16122 NULL, type, NULL,
16123 "Internal error: xmlSchemaTypeFixup, "
16124 "complex type '%s': the <simpleContent><restriction> "
16125 "is missing a <simpleType> child, but was not catched "
16126 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016127 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016128 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16129 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16130 /*
16131 * SPEC (3) If <extension> + base is <complexType> with
16132 * <simpleType> content, "...then the {content type} of that
16133 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016134 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016135 if (baseType->contentTypeDef == NULL) {
16136 /*
16137 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16138 * should have catched this already.
16139 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016140 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016141 XML_SCHEMAP_INTERNAL,
16142 NULL, type, NULL,
16143 "Internal error: xmlSchemaTypeFixup, "
16144 "complex type '%s': the <extension>ed base type is "
16145 "a complex type with no simple content type",
16146 type->name);
16147 }
16148 type->contentTypeDef = baseType->contentTypeDef;
16149 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16150 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16151 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016152 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016153 * "... then that simple type definition"
16154 */
16155 type->contentTypeDef = baseType;
16156 } else {
16157 /*
16158 * TODO: Check if this ever happens.
16159 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016160 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016161 XML_SCHEMAP_INTERNAL,
16162 NULL, type, NULL,
16163 "Internal error: xmlSchemaTypeFixup, "
16164 "complex type '%s' with <simpleContent>: unhandled "
16165 "derivation case", type->name);
16166 }
16167 } else {
16168 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016169 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016170 (xmlSchemaParticlePtr) type->subtypes;
16171 /*
16172 * Corresponds to <complexType><complexContent>...
16173 *
16174 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016175 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016176 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016177 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016178 * Compute the "effective content":
16179 * (2.1.1) + (2.1.2) + (2.1.3)
16180 */
16181 if ((particle == NULL) ||
16182 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16183 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16184 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16185 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16186 (particle->minOccurs == 0))) &&
16187 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016188 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016189 /*
16190 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16191 * a particle whose properties are as follows:..."
16192 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016193 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016194 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16195 * NOTE that we sill assign it the <complexType> node to
16196 * somehow anchor it in the doc.
16197 */
16198 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016199 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016200 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016201 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016202 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016203 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016204 type->node, 1, 1);
16205 if (particle == NULL)
16206 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016207 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016208 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016209 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016210 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016211 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016212 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16213 if (particle->children == NULL)
16214 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016215
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016216 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016217 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016218 dummySequence = 1;
16219 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16220 } else {
16221 /*
16222 * SPEC (2.1.5) "otherwise empty"
16223 */
16224 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016225 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016226 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016227 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016228 * SPEC (2.2) "otherwise the particle corresponding to the
16229 * <all>, <choice>, <group> or <sequence> among the
16230 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016231 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016232 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16233 }
16234 /*
16235 * Compute the "content type".
16236 */
16237 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016238 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016239 * SPEC (3.1) "If <restriction>..."
16240 * (3.1.1) + (3.1.2) */
16241 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16242 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16243 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16244 }
16245 } else {
16246 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016247 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016248 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016249 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16250 /*
16251 * SPEC (3.2.1)
16252 */
16253 type->contentType = baseType->contentType;
16254 type->subtypes = baseType->subtypes;
16255 /*
16256 * NOTE that the effective mixed is ignored here.
16257 */
16258 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16259 /*
16260 * SPEC (3.2.2)
16261 */
16262 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16263 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16264 } else {
16265 /*
16266 * SPEC (3.2.3)
16267 */
16268 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16269 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16270 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016271 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016272 * {particles} are..."
16273 */
16274 if (! dummySequence) {
16275 xmlSchemaTreeItemPtr effectiveContent =
16276 (xmlSchemaTreeItemPtr) type->subtypes;
16277 /*
16278 * Create the particle.
16279 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016280 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016281 type->node, 1, 1);
16282 if (particle == NULL)
16283 return;
16284 /*
16285 * Create the "sequence" model group.
16286 */
16287 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016288 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016289 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16290 if (particle->children == NULL)
16291 return;
16292 type->subtypes = (xmlSchemaTypePtr) particle;
16293 /*
16294 * SPEC "the particle of the {content type} of
16295 * the ... base ..."
16296 * Create a duplicate of the base type's particle
16297 * and assign its "term" to it.
16298 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016299 particle->children->children =
16300 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16301 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016302 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016303 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016304 if (particle->children->children == NULL)
16305 return;
16306 particle = (xmlSchemaParticlePtr)
16307 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016308 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016309 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16310 /*
16311 * SPEC "followed by the ·effective content·."
16312 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016313 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016314 } else {
16315 /*
16316 * This is the case when there is already an empty
16317 * <sequence> with minOccurs==maxOccurs==1.
16318 * Just add the base types's content type.
16319 * NOTE that, although we miss to add an intermediate
16320 * <sequence>, this should produce no difference to
16321 * neither the regex compilation of the content model,
16322 * nor to the complex type contraints.
16323 */
16324 particle->children->children =
16325 (xmlSchemaTreeItemPtr) baseType->subtypes;
16326 }
16327 }
16328 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016329 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016330 /*
16331 * Apply the complex type component constraints; this will not
16332 * check attributes, since this is done in
16333 * xmlSchemaBuildAttributeValidation().
16334 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016335 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16336 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016337 /*
16338 * Inherit & check constraints for attributes.
16339 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016340 xmlSchemaBuildAttributeValidation(pctxt, type);
16341 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016342 /*
16343 * Simple Type Definition Schema Component
16344 */
16345 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016346 if (VARIETY_LIST(type)) {
16347 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016348 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016349 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016350 if (type->subtypes == NULL) {
16351 /*
16352 * This one is really needed, so get out.
16353 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016354 PERROR_INT("xmlSchemaTypeFixup",
16355 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016356 return;
16357 }
16358 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016359 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16360 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016361 /*
16362 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016363 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016364 if (type->memberTypes == NULL) {
16365 /*
16366 * This one is really needed, so get out.
16367 */
16368 return;
16369 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016370 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016371 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016372 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016373 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016374 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016375 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016377 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016378 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16379 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016380 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016381 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016382 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016383 */
16384 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016385 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016386 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016387 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16388 /*
16389 * Inherit the itemType.
16390 */
16391 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016392 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016393 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16394 /*
16395 * NOTE that we won't assign the memberTypes of the base,
16396 * since this will make trouble when freeing them; we will
16397 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016398 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016399 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016400 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016401 /*
16402 * Check constraints.
16403 *
16404 * TODO: Split this somehow, we need to know first if we can derive
16405 * from the base type at all!
16406 */
16407 if (type->baseType != NULL) {
16408 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016409 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016410 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016411 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016412 * applied beforehand.
16413 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016414 xmlSchemaCheckSRCSimpleType(pctxt, type);
16415 xmlSchemaCheckFacetValues(type, pctxt);
16416 if ((type->facetSet != NULL) ||
16417 (type->baseType->facetSet != NULL))
16418 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16419 /*
16420 * Whitespace value.
16421 */
16422 xmlSchemaTypeFixupWhitespace(type);
16423 xmlSchemaTypeFixupOptimFacets(type);
16424 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016425 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016426
Daniel Veillard8651f532002-04-17 09:06:27 +000016427#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016428 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016429 xmlGenericError(xmlGenericErrorContext,
16430 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016431 type->node->doc->URL,
16432 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016433 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016434 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016435 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016436 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16437 switch (type->contentType) {
16438 case XML_SCHEMA_CONTENT_SIMPLE:
16439 xmlGenericError(xmlGenericErrorContext, "simple\n");
16440 break;
16441 case XML_SCHEMA_CONTENT_ELEMENTS:
16442 xmlGenericError(xmlGenericErrorContext, "elements\n");
16443 break;
16444 case XML_SCHEMA_CONTENT_UNKNOWN:
16445 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16446 break;
16447 case XML_SCHEMA_CONTENT_EMPTY:
16448 xmlGenericError(xmlGenericErrorContext, "empty\n");
16449 break;
16450 case XML_SCHEMA_CONTENT_MIXED:
16451 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016452 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016453 xmlGenericError(xmlGenericErrorContext,
16454 "mixed as emptiable particle\n");
16455 else
16456 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16457 break;
16458 /* Removed, since not used. */
16459 /*
16460 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16461 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16462 break;
16463 */
16464 case XML_SCHEMA_CONTENT_BASIC:
16465 xmlGenericError(xmlGenericErrorContext, "basic\n");
16466 break;
16467 default:
16468 xmlGenericError(xmlGenericErrorContext,
16469 "not registered !!!\n");
16470 break;
16471 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016472 }
16473#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016474}
16475
16476/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016477 * xmlSchemaCheckFacet:
16478 * @facet: the facet
16479 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016480 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016481 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016482 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016483 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016484 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016485 * Returns 0 if valid, a positive error code if not valid and
16486 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016487 */
16488int
16489xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016490 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016491 xmlSchemaParserCtxtPtr pctxt,
16492 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016493{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016494 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016495
Daniel Veillardce682bc2004-11-05 17:22:25 +000016496 if ((facet == NULL) || (typeDecl == NULL))
16497 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016498 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016499 * TODO: will the parser context be given if used from
16500 * the relaxNG module?
16501 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016502 if (pctxt == NULL)
16503 ctxtGiven = 0;
16504 else
16505 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016506
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016507 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016508 case XML_SCHEMA_FACET_MININCLUSIVE:
16509 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16510 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016511 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16512 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016513 /*
16514 * Okay we need to validate the value
16515 * at that point.
16516 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016517 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016518
16519 /* 4.3.5.5 Constraints on enumeration Schema Components
16520 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016521 * It is an ·error· if any member of {value} is not in the
16522 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016523 *
16524 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016525 * The value ·must· be in the
16526 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016527 */
16528 /*
16529 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016530 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016531 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016532 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016533 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016534 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016535 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016536 */
16537 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16538 base = typeDecl->baseType;
16539 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016540 PERROR_INT("xmlSchemaCheckFacet",
16541 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016542 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016543 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016544 } else
16545 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016546
16547 if (! ctxtGiven) {
16548 /*
16549 * A context is needed if called from RelaxNG.
16550 */
16551 pctxt = xmlSchemaNewParserCtxt("*");
16552 if (pctxt == NULL)
16553 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016554 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016555 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016556 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016557 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016558 * facet->node is just the node holding the facet
16559 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016560 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016561 */
16562 ret = xmlSchemaVCheckCVCSimpleType(
16563 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16564 facet->value, &(facet->val), 1, 1, 0);
16565 if (ret != 0) {
16566 if (ret < 0) {
16567 /* No error message for RelaxNG. */
16568 if (ctxtGiven) {
16569 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16570 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16571 "Internal error: xmlSchemaCheckFacet, "
16572 "failed to validate the value '%s' of the "
16573 "facet '%s' against the base type",
16574 facet->value, xmlSchemaFacetTypeToString(facet->type));
16575 }
16576 goto internal_error;
16577 }
16578 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16579 /* No error message for RelaxNG. */
16580 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016581 xmlChar *str = NULL;
16582
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016583 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16584 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016585 "The value '%s' of the facet does not validate "
16586 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016587 facet->value,
16588 xmlSchemaFormatQName(&str,
16589 base->targetNamespace, base->name));
16590 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016591 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016592 goto exit;
16593 } else if (facet->val == NULL) {
16594 if (ctxtGiven) {
16595 PERROR_INT("xmlSchemaCheckFacet",
16596 "value was not computed");
16597 }
16598 TODO
16599 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016600 break;
16601 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016602 case XML_SCHEMA_FACET_PATTERN:
16603 facet->regexp = xmlRegexpCompile(facet->value);
16604 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016605 ret = XML_SCHEMAP_REGEXP_INVALID;
16606 /* No error message for RelaxNG. */
16607 if (ctxtGiven) {
16608 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16609 ret, facet->node, typeDecl,
16610 "The value '%s' of the facet 'pattern' is not a "
16611 "valid regular expression",
16612 facet->value, NULL);
16613 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016614 }
16615 break;
16616 case XML_SCHEMA_FACET_TOTALDIGITS:
16617 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16618 case XML_SCHEMA_FACET_LENGTH:
16619 case XML_SCHEMA_FACET_MAXLENGTH:
16620 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016621 ret = xmlSchemaValidatePredefinedType(
16622 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16623 facet->value, &(facet->val));
16624 if (ret != 0) {
16625 if (ret < 0) {
16626 /* No error message for RelaxNG. */
16627 if (ctxtGiven) {
16628 PERROR_INT("xmlSchemaCheckFacet",
16629 "validating facet value");
16630 }
16631 goto internal_error;
16632 }
16633 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16634 /* No error message for RelaxNG. */
16635 if (ctxtGiven) {
16636 /* error code */
16637 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16638 ret, facet->node, typeDecl,
16639 "The value '%s' of the facet '%s' is not a valid "
16640 "'nonNegativeInteger'",
16641 facet->value,
16642 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016643 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016644 }
16645 break;
16646 }
16647 case XML_SCHEMA_FACET_WHITESPACE:{
16648 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16649 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16650 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16651 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16652 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16653 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16654 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016655 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16656 /* No error message for RelaxNG. */
16657 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016658 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016659 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16660 ret, facet->node, typeDecl,
16661 "The value '%s' of the facet 'whitespace' is not "
16662 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016663 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016664 }
16665 }
16666 default:
16667 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016668 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016669exit:
16670 if ((! ctxtGiven) && (pctxt != NULL))
16671 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016672 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016673internal_error:
16674 if ((! ctxtGiven) && (pctxt != NULL))
16675 xmlSchemaFreeParserCtxt(pctxt);
16676 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016677}
16678
16679/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016680 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016681 * @typeDecl: the schema type definition
16682 * @ctxt: the schema parser context
16683 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016684 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016685 */
16686static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016687xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16688 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016689{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016690 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016691 /*
16692 * NOTE: It is intended to use the facets list, instead
16693 * of facetSet.
16694 */
16695 if (typeDecl->facets != NULL) {
16696 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016697
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016698 /*
16699 * Temporarily assign the "schema" to the validation context
16700 * of the parser context. This is needed for NOTATION validation.
16701 */
16702 if (ctxt->vctxt == NULL) {
16703 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16704 return;
16705 }
16706 ctxt->vctxt->schema = ctxt->schema;
16707
Daniel Veillard01fa6152004-06-29 17:04:39 +000016708 while (facet != NULL) {
16709 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16710 facet = facet->next;
16711 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016712
16713 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016714 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016715}
16716
16717/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016718 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016719 * @ctxtMGroup: the searched model group
16720 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016721 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016722 *
16723 * This one is intended to be used by
16724 * xmlSchemaCheckGroupDefCircular only.
16725 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016726 * Returns the particle with the circular model group definition reference,
16727 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016728 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016729static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016730xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016731 xmlSchemaTreeItemPtr particle)
16732{
16733 xmlSchemaTreeItemPtr circ = NULL;
16734 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016735 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016736
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016737 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016738 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016739 if (term == NULL)
16740 continue;
16741 switch (term->type) {
16742 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016743 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016744 if (gdef == groupDef)
16745 return (particle);
16746 /*
16747 * Mark this model group definition to avoid infinite
16748 * recursion on circular references not yet examined.
16749 */
16750 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16751 continue;
16752 if (gdef->children != NULL) {
16753 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16754 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16755 gdef->children->children);
16756 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16757 if (circ != NULL)
16758 return (circ);
16759 }
16760 break;
16761 case XML_SCHEMA_TYPE_SEQUENCE:
16762 case XML_SCHEMA_TYPE_CHOICE:
16763 case XML_SCHEMA_TYPE_ALL:
16764 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16765 if (circ != NULL)
16766 return (circ);
16767 break;
16768 default:
16769 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016770 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016771 }
16772 return (NULL);
16773}
16774
16775/**
16776 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016777 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016778 * @ctxt: the parser context
16779 * @name: the name
16780 *
16781 * Checks for circular references to model group definitions.
16782 */
16783static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016784xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016785 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016786 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016787{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016788 /*
16789 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016790 * 2 Circular groups are disallowed. That is, within the {particles}
16791 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016792 * is the group itself.
16793 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016794 if ((item == NULL) ||
16795 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16796 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016797 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016798 {
16799 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016800
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016801 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016802 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016803 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016804 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016805 * TODO: The error report is not adequate: this constraint
16806 * is defined for model groups but not definitions, but since
16807 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016808 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016809 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016810 */
16811 xmlSchemaPCustomErr(ctxt,
16812 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016813 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016814 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016815 "defined", xmlSchemaFormatQName(&str,
16816 item->targetNamespace, item->name));
16817 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016818 /*
16819 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016820 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016821 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016822 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016823 }
16824 }
16825}
16826
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016827/**
16828 * xmlSchemaGroupDefTermFixup:
16829 * @item: the particle with a model group definition as term
16830 * @ctxt: the parser context
16831 * @name: the name
16832 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016833 * Checks cos-all-limited.
16834 *
16835 * Assigns the model group of model group definitions to the "term"
16836 * of the referencing particle.
16837 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16838 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016839 */
16840static void
16841xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016842 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016843 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016844{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016845 if ((item == NULL) ||
16846 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16847 (item->children == NULL) ||
16848 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16849 (item->children->children == NULL))
16850 return;
16851 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016852 /*
16853 * TODO: Not nice, but we will anchor cos-all-limited here.
16854 */
16855 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16856 (item->maxOccurs != 1)) {
16857 /*
16858 * SPEC (1.2) "the {term} property of a particle with
16859 * {max occurs}=1which is part of a pair which constitutes the
16860 * {content type} of a complex type definition."
16861 */
16862 xmlSchemaPCustomErr(ctxt,
16863 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16864 NULL, (xmlSchemaTypePtr) item, item->node,
16865 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16866 "group is its term", NULL);
16867 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016868}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016869
16870/**
16871 * xmlSchemaGetCircAttrGrRef:
16872 * @ctxtGr: the searched attribute group
16873 * @attr: the current attribute list to be processed
16874 *
16875 * This one is intended to be used by
16876 * xmlSchemaCheckSRCAttributeGroupCircular only.
16877 *
16878 * Returns the circular attribute grou reference, otherwise NULL.
16879 */
16880static xmlSchemaAttributeGroupPtr
16881xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16882 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016883{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016884 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16885 int marked;
16886 /*
16887 * We will search for an attribute group reference which
16888 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016889 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016890 while (attr != NULL) {
16891 marked = 0;
16892 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16893 gr = (xmlSchemaAttributeGroupPtr) attr;
16894 if (gr->refItem != NULL) {
16895 if (gr->refItem == ctxtGr)
16896 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016897 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016898 XML_SCHEMAS_ATTRGROUP_MARKED) {
16899 attr = attr->next;
16900 continue;
16901 } else {
16902 /*
16903 * Mark as visited to avoid infinite recursion on
16904 * circular references not yet examined.
16905 */
16906 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16907 marked = 1;
16908 }
16909 }
16910 if (gr->attributes != NULL)
16911 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16912 /*
16913 * Unmark the visited group's attributes.
16914 */
16915 if (marked)
16916 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16917 if (circ != NULL)
16918 return (circ);
16919 }
16920 attr = attr->next;
16921 }
16922 return (NULL);
16923}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016924
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016925/**
16926 * xmlSchemaCheckSRCAttributeGroupCircular:
16927 * attrGr: the attribute group definition
16928 * @ctxt: the parser context
16929 * @name: the name
16930 *
16931 * Checks for circular references of attribute groups.
16932 */
16933static void
16934xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016935 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016936 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016937{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016938 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016939 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016940 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016941 * 3 Circular group reference is disallowed outside <redefine>.
16942 * That is, unless this element information item's parent is
16943 * <redefine>, then among the [children], if any, there must
16944 * not be an <attributeGroup> with ref [attribute] which resolves
16945 * to the component corresponding to this <attributeGroup>. Indirect
16946 * circularity is also ruled out. That is, when QName resolution
16947 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16948 * any <attributeGroup>s with a ref [attribute] among the [children],
16949 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016950 * which resolves to the component corresponding to this <attributeGroup>.
16951 */
16952 /*
16953 * Only global components can be referenced.
16954 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016955 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016956 (attrGr->attributes == NULL))
16957 return;
16958 else {
16959 xmlSchemaAttributeGroupPtr circ;
16960
16961 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16962 if (circ != NULL) {
16963 /*
16964 * TODO: Report the referenced attr group as QName.
16965 */
16966 xmlSchemaPCustomErr(ctxt,
16967 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16968 NULL, NULL, circ->node,
16969 "Circular reference to the attribute group '%s' "
16970 "defined", attrGr->name);
16971 /*
16972 * NOTE: We will cut the reference to avoid further
16973 * confusion of the processor.
16974 * BADSPEC: The spec should define how to process in this case.
16975 */
16976 circ->attributes = NULL;
16977 circ->refItem = NULL;
16978 }
16979 }
16980}
16981
16982/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016983 * xmlSchemaAttrGrpFixup:
16984 * @attrgrpDecl: the schema attribute definition
16985 * @ctxt: the schema parser context
16986 * @name: the attribute name
16987 *
16988 * Fixes finish doing the computations on the attributes definitions
16989 */
16990static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016991xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016992 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016993{
16994 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016995 name = attrgrp->name;
16996 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016997 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016998 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016999 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017000
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017001 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017002 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017003 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017004 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017005 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017006 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17007 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017008 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017009 return;
17010 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017011 attrgrp->refItem = ref;
17012 /*
17013 * Check for self reference!
17014 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017015 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017016 attrgrp->attributes = ref->attributes;
17017 attrgrp->attributeWildcard = ref->attributeWildcard;
17018 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017019}
17020
17021/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017022 * xmlSchemaAttrCheckValConstr:
17023 * @item: an schema attribute declaration/use
17024 * @ctxt: a schema parser context
17025 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017026 *
17027 *
17028 * Schema Component Constraint: Attribute Declaration Properties Correct
17029 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017030 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017031 *
17032 * Fixes finish doing the computations on the attributes definitions
17033 */
17034static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017035xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017036 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017037 const xmlChar * name ATTRIBUTE_UNUSED)
17038{
17039
17040 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017041 * 2 if there is a {value constraint}, the canonical lexical
17042 * representation of its value must be ·valid· with respect
17043 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017044 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017045 if (item->defValue != NULL) {
17046 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017047
17048 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017049 PERROR_INT("xmlSchemaCheckAttrValConstr",
17050 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017051 return;
17052 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017053 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17054 item->node, item->subtypes, item->defValue, &(item->defVal),
17055 1, 1, 0);
17056 if (ret != 0) {
17057 if (ret < 0) {
17058 PERROR_INT("xmlSchemaAttrCheckValConstr",
17059 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017060 return;
17061 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017062 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17063 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17064 ret, item->node, (xmlSchemaTypePtr) item,
17065 "The value of the value constraint is not valid", NULL, NULL);
17066 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017067 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017068 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017069}
17070
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017071static xmlSchemaElementPtr
17072xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17073 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017074{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017075 xmlSchemaElementPtr ret;
17076
17077 if (SUBST_GROUP_AFF(ancestor) == NULL)
17078 return (NULL);
17079 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17080 return (ancestor);
17081
17082 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17083 return (NULL);
17084 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17085 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17086 SUBST_GROUP_AFF(ancestor));
17087 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17088
17089 return (ret);
17090}
17091
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017092/**
17093 * xmlSchemaCheckElemPropsCorrect:
17094 * @ctxt: a schema parser context
17095 * @decl: the element declaration
17096 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017097 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017098 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017099 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017100 *
17101 * STATUS:
17102 * missing: (6)
17103 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017104static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017105xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17106 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017107{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017108 int ret = 0;
17109 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017110 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017111 * SPEC (1) "The values of the properties of an element declaration
17112 * must be as described in the property tableau in The Element
17113 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17114 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017115 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017116 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017117 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017118
17119 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017120 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017121 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017122 * affiliation}, then {scope} must be global."
17123 */
17124 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17125 xmlSchemaPCustomErr(pctxt,
17126 XML_SCHEMAP_E_PROPS_CORRECT_3,
17127 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17128 "Only global element declarations can have a "
17129 "substitution group affiliation", NULL);
17130 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017131 }
17132 /*
17133 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17134 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017135 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017136 * property."
17137 */
17138 if (head == elemDecl)
17139 circ = head;
17140 else if (SUBST_GROUP_AFF(head) != NULL)
17141 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17142 else
17143 circ = NULL;
17144 if (circ != NULL) {
17145 xmlChar *strA = NULL, *strB = NULL;
17146
17147 xmlSchemaPCustomErrExt(pctxt,
17148 XML_SCHEMAP_E_PROPS_CORRECT_6,
17149 NULL, (xmlSchemaTypePtr) circ, circ->node,
17150 "The element declaration '%s' defines a circular "
17151 "substitution group to element declaration '%s'",
17152 xmlSchemaGetComponentQName(&strA, circ),
17153 xmlSchemaGetComponentQName(&strB, head),
17154 NULL);
17155 FREE_AND_NULL(strA)
17156 FREE_AND_NULL(strB)
17157 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17158 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017159 /*
17160 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017161 * the {type definition}
17162 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017163 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017164 * of the {substitution group exclusions} of the {substitution group
17165 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17166 * (if the {type definition} is complex) or as defined in
17167 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017168 * simple)."
17169 *
17170 * NOTE: {substitution group exclusions} means the values of the
17171 * attribute "final".
17172 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017173
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017174 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017175 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017176
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017177 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17178 set |= SUBSET_EXTENSION;
17179 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17180 set |= SUBSET_RESTRICTION;
17181
17182 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17183 ELEM_TYPE(head), set) != 0) {
17184 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17185
17186 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017187 xmlSchemaPCustomErrExt(pctxt,
17188 XML_SCHEMAP_E_PROPS_CORRECT_4,
17189 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017190 "The type definition '%s' was "
17191 "either rejected by the substitution group "
17192 "affiliation '%s', or not validly derived from its type "
17193 "definition '%s'",
17194 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017195 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017196 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017197 FREE_AND_NULL(strA)
17198 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017199 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017200 }
17201 }
17202 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017203 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017204 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017205 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017206 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017207 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017208 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017209 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017210 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017211 ((IS_SIMPLE_TYPE(typeDef) &&
17212 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017213 (IS_COMPLEX_TYPE(typeDef) &&
17214 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017215 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17216 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017217
17218 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17219 xmlSchemaPCustomErr(pctxt,
17220 XML_SCHEMAP_E_PROPS_CORRECT_5,
17221 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17222 "The type definition (or type definition's content type) is or "
17223 "is derived from ID; value constraints are not allowed in "
17224 "conjunction with such a type definition", NULL);
17225 } else if (elemDecl->value != NULL) {
17226 int vcret;
17227 xmlNodePtr node = NULL;
17228
17229 /*
17230 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17231 * representation of its value must be ·valid· with respect to the
17232 * {type definition} as defined in Element Default Valid (Immediate)
17233 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017234 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017235 if (typeDef == NULL) {
17236 xmlSchemaPErr(pctxt, elemDecl->node,
17237 XML_SCHEMAP_INTERNAL,
17238 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17239 "type is missing... skipping validation of "
17240 "the value constraint", NULL, NULL);
17241 return (-1);
17242 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017243 if (elemDecl->node != NULL) {
17244 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17245 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17246 BAD_CAST "fixed");
17247 else
17248 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17249 BAD_CAST "default");
17250 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017251 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17252 typeDef, elemDecl->value, &(elemDecl->defVal));
17253 if (vcret != 0) {
17254 if (vcret < 0) {
17255 PERROR_INT("xmlSchemaElemCheckValConstr",
17256 "failed to validate the value constraint of an "
17257 "element declaration");
17258 return (-1);
17259 }
17260 return (vcret);
17261 }
17262 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017263
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017264 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017265}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017266
17267/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017268 * xmlSchemaCheckElemSubstGroup:
17269 * @ctxt: a schema parser context
17270 * @decl: the element declaration
17271 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017272 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017273 * Schema Component Constraint:
17274 * Substitution Group (cos-equiv-class)
17275 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017276 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017277 * a list will be built for each subst. group head, holding all direct
17278 * referents to this head.
17279 * NOTE that this function needs:
17280 * 1. circular subst. groups to be checked beforehand
17281 * 2. the declaration's type to be derived from the head's type
17282 *
17283 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017284 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017285 */
17286static void
17287xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17288 xmlSchemaElementPtr elemDecl)
17289{
17290 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17291 /* SPEC (1) "Its {abstract} is false." */
17292 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17293 return;
17294 {
17295 xmlSchemaElementPtr head;
17296 xmlSchemaTypePtr headType, type;
17297 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017298 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017299 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17300 * {disallowed substitutions} as the blocking constraint, as defined in
17301 * Substitution Group OK (Transitive) (§3.3.6)."
17302 */
17303 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17304 head = SUBST_GROUP_AFF(head)) {
17305 set = 0;
17306 methSet = 0;
17307 /*
17308 * The blocking constraints.
17309 */
17310 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17311 continue;
17312 headType = head->subtypes;
17313 type = elemDecl->subtypes;
17314 if (headType == type)
17315 goto add_member;
17316 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17317 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17318 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17319 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17320 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017321 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017322 * "The set of all {derivation method}s involved in the
17323 * derivation of D's {type definition} from C's {type definition}
17324 * does not intersect with the union of the blocking constraint,
17325 * C's {prohibited substitutions} (if C is complex, otherwise the
17326 * empty set) and the {prohibited substitutions} (respectively the
17327 * empty set) of any intermediate {type definition}s in the
17328 * derivation of D's {type definition} from C's {type definition}."
17329 */
17330 /*
17331 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17332 * subst.head axis, the methSet does not need to be computed for
17333 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017334 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017335 /*
17336 * The set of all {derivation method}s involved in the derivation
17337 */
17338 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017339 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017340 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17341 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17342 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017343
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017344 if ((type->flags &
17345 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17346 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17347 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17348
17349 type = type->baseType;
17350 }
17351 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017352 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017353 * the head's type.
17354 */
17355 type = elemDecl->subtypes->baseType;
17356 while (type != NULL) {
17357 if (IS_COMPLEX_TYPE(type)) {
17358 if ((type->flags &
17359 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17360 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17361 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17362 if ((type->flags &
17363 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17364 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17365 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17366 } else
17367 break;
17368 if (type == headType)
17369 break;
17370 type = type->baseType;
17371 }
17372 if ((set != 0) &&
17373 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17374 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17375 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17376 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17377 continue;
17378 }
17379add_member:
17380 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17381 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17382 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17383 }
17384 }
17385}
17386
17387/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017388 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017389 * @item: an schema element declaration/particle
17390 * @ctxt: a schema parser context
17391 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017392 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017393 * Validates the value constraints of an element declaration.
17394 *
17395 * Fixes finish doing the computations on the element declarations.
17396 */
17397static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017398xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017399 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017400 const xmlChar * name ATTRIBUTE_UNUSED)
17401{
17402 if (elemDecl == NULL)
17403 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017404 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17405 return;
17406 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017407 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17408 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017409}
17410
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017411/**
17412 * xmlSchemaMiscRefFixup:
17413 * @item: an schema component
17414 * @ctxt: a schema parser context
17415 * @name: the internal name of the component
17416 *
17417 * Resolves references of misc. schema components.
17418 */
17419static void
17420xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017421 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017422 const xmlChar * name ATTRIBUTE_UNUSED)
17423{
17424 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017425 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017426 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17427 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17428 xmlSchemaTreeItemPtr refItem;
17429 /*
17430 * Resolve the reference.
17431 */
17432 item->children = NULL;
17433 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17434 ref->itemType, ref->name, ref->targetNamespace);
17435 if (refItem == NULL) {
17436 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017437 NULL, GET_NODE(item), "ref", ref->name,
17438 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017439 } else {
17440 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17441 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017442 * NOTE that we will assign the model group definition
17443 * itself to the "term" of the particle. This will ease
17444 * the check for circular model group definitions. After
17445 * that the "term" will be assigned the model group of the
17446 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017447 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017448 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017449 } else
17450 item->children = refItem;
17451 }
17452 }
17453 }
17454}
17455
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017456static int
17457xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17458 xmlSchemaValPtr y)
17459{
17460 xmlSchemaTypePtr tx, ty, ptx, pty;
17461 int ret;
17462
17463 while (x != NULL) {
17464 /* Same types. */
17465 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17466 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17467 ptx = xmlSchemaGetPrimitiveType(tx);
17468 pty = xmlSchemaGetPrimitiveType(ty);
17469 /*
17470 * (1) if a datatype T' is ·derived· by ·restriction· from an
17471 * atomic datatype T then the ·value space· of T' is a subset of
17472 * the ·value space· of T. */
17473 /*
17474 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17475 * from a common atomic ancestor T then the ·value space·s of T'
17476 * and T'' may overlap.
17477 */
17478 if (ptx != pty)
17479 return(0);
17480 /*
17481 * We assume computed values to be normalized, so do a fast
17482 * string comparison for string based types.
17483 */
17484 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17485 IS_ANY_SIMPLE_TYPE(ptx)) {
17486 if (! xmlStrEqual(
17487 xmlSchemaValueGetAsString(x),
17488 xmlSchemaValueGetAsString(y)))
17489 return (0);
17490 } else {
17491 ret = xmlSchemaCompareValuesWhtsp(
17492 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17493 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17494 if (ret == -2)
17495 return(-1);
17496 if (ret != 0)
17497 return(0);
17498 }
17499 /*
17500 * Lists.
17501 */
17502 x = xmlSchemaValueGetNext(x);
17503 if (x != NULL) {
17504 y = xmlSchemaValueGetNext(y);
17505 if (y == NULL)
17506 return (0);
17507 } else if (xmlSchemaValueGetNext(y) != NULL)
17508 return (0);
17509 else
17510 return (1);
17511 }
17512 return (0);
17513}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017514
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017515/**
17516 * xmlSchemaAttrFixup:
17517 * @item: an schema attribute declaration/use.
17518 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017519 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017520 *
17521 * Fixes finish doing the computations on attribute declarations/uses.
17522 */
17523static void
17524xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017525 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017526 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017527{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017528 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017529 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017530 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017531 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017532 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017533 * The simple type definition corresponding to the <simpleType> element
17534 * information item in the [children], if present, otherwise the simple
17535 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017536 * [attribute], if present, otherwise the ·simple ur-type definition·.
17537 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017538 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017539 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017540 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17541 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017542 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017543 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017544 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017545
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017546 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17547 item->typeNs);
17548 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017549 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017550 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017551 (xmlSchemaTypePtr) item, item->node,
17552 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017553 XML_SCHEMA_TYPE_SIMPLE, NULL);
17554 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017555 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017556
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017557 } else if (item->ref != NULL) {
17558 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017559
Daniel Veillardc0826a72004-08-10 14:17:33 +000017560 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017561 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017562 * attribute declaration.
17563 */
17564 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017565 * TODO: Evaluate, what errors could occur if the declaration is not
17566 * found. It might be possible that the "typefixup" might crash if
17567 * no ref declaration was found.
17568 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017569 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017570 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017571 xmlSchemaPResCompAttrErr(ctxt,
17572 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017573 (xmlSchemaTypePtr) item, item->node,
17574 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017575 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017576 return;
17577 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017578 item->refDecl = decl;
17579 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017580 item->subtypes = decl->subtypes;
17581 /*
17582 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017583 * au-props-correct.2: If the {attribute declaration} has a fixed
17584 * {value constraint}, then if the attribute use itself has a
17585 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017586 * that of the {attribute declaration}'s {value constraint}.
17587 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017588 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017589 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017590 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017591 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017592 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17593 NULL, NULL, item->node,
17594 "The attribute declaration has a 'fixed' value constraint "
17595 ", thus it must be 'fixed' in attribute use as well",
17596 NULL);
17597 } else {
17598 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17599 xmlSchemaPCustomErr(ctxt,
17600 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17601 NULL, NULL, item->node,
17602 "The 'fixed' value constraint of the attribute use "
17603 "must match the attribute declaration's value "
17604 "constraint '%s'",
17605 decl->defValue);
17606 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017607 }
17608 /*
17609 * FUTURE: One should change the values of the attr. use
17610 * if ever validation should be attempted even if the
17611 * schema itself was not fully valid.
17612 */
17613 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017614 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017615 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17616 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017617}
17618
17619/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017620 * xmlSchemaResolveIDCKeyRef:
17621 * @idc: the identity-constraint definition
17622 * @ctxt: the schema parser context
17623 * @name: the attribute name
17624 *
17625 * Resolve keyRef references to key/unique IDCs.
17626 */
17627static void
17628xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017629 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017630 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017631{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017632 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17633 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017634 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017635 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017636 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017637 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017638 idc->ref->targetNamespace);
17639 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017640 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017641 * TODO: It is actually not an error to fail to resolve.
17642 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017643 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017644 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017645 (xmlSchemaTypePtr) idc, idc->node,
17646 "refer", idc->ref->name,
17647 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017648 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17649 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017650 } else {
17651 if (idc->nbFields !=
17652 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17653 xmlChar *str = NULL;
17654 xmlSchemaIDCPtr refer;
17655
17656 refer = (xmlSchemaIDCPtr) idc->ref->item;
17657 /*
17658 * SPEC c-props-correct(2)
17659 * "If the {identity-constraint category} is keyref,
17660 * the cardinality of the {fields} must equal that of
17661 * the {fields} of the {referenced key}.
17662 */
17663 xmlSchemaPCustomErr(pctxt,
17664 XML_SCHEMAP_C_PROPS_CORRECT,
17665 NULL, (xmlSchemaTypePtr) idc, idc->node,
17666 "The cardinality of the keyref differs from the "
17667 "cardinality of the referenced key '%s'",
17668 xmlSchemaFormatQName(&str, refer->targetNamespace,
17669 refer->name)
17670 );
17671 FREE_AND_NULL(str)
17672 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017673 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017674 }
17675}
17676
17677/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017678 * xmlSchemaParse:
17679 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017680 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017681 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017682 * XML Shema struture which can be used to validate instances.
17683 * *WARNING* this interface is highly subject to change
17684 *
17685 * Returns the internal XML Schema structure built from the resource or
17686 * NULL in case of error
17687 */
17688xmlSchemaPtr
17689xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17690{
17691 xmlSchemaPtr ret = NULL;
17692 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017693 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017694 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017695
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017696 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017697 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017698 * the API; i.e. not automatically by the validated instance document.
17699 */
17700
Daniel Veillard4255d502002-04-16 15:50:10 +000017701 xmlSchemaInitTypes();
17702
Daniel Veillard6045c902002-10-09 21:13:59 +000017703 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017704 return (NULL);
17705
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017706 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017707 ctxt->counter = 0;
17708 ctxt->container = NULL;
17709
17710 /*
17711 * First step is to parse the input document into an DOM/Infoset
17712 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017713 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017714 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017715 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017716 if (doc == NULL) {
17717 xmlSchemaPErr(ctxt, NULL,
17718 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017719 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017720 ctxt->URL, NULL);
17721 return (NULL);
17722 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017723 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017724 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17725 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017726 if (doc == NULL) {
17727 xmlSchemaPErr(ctxt, NULL,
17728 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017729 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017730 NULL, NULL);
17731 return (NULL);
17732 }
17733 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017734 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017735 } else if (ctxt->doc != NULL) {
17736 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017737 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017738 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017739 xmlSchemaPErr(ctxt, NULL,
17740 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017741 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017742 NULL, NULL);
17743 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017744 }
17745
17746 /*
17747 * Then extract the root and Schema parse it
17748 */
17749 root = xmlDocGetRootElement(doc);
17750 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017751 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17752 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017753 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017754 if (!preserve) {
17755 xmlFreeDoc(doc);
17756 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017757 return (NULL);
17758 }
17759
17760 /*
17761 * Remove all the blank text nodes
17762 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017763 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017764
17765 /*
17766 * Then do the parsing for good
17767 */
17768 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017769 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017770 if (!preserve) {
17771 xmlFreeDoc(doc);
17772 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017773 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017774 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017775 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017776 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017777 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017778 ctxt->ctxtType = NULL;
17779 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017780
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017781 /*
17782 * Resolve base types of simple/complex types.
17783 */
17784 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017785
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017786 if (ctxt->nberrors != 0)
17787 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017788
17789 if (ret->volatiles != NULL) {
17790 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17791 int i;
17792 xmlSchemaTreeItemPtr item;
17793
17794 for (i = 0; i < list->nbItems; i++) {
17795 item = (xmlSchemaTreeItemPtr) list->items[i];
17796 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17797 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017798 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017799 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017800 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017801 * Then fixup all attributes declarations
17802 */
17803 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017804 /*
17805 * Then fixup all attributes group declarations
17806 */
17807 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17808 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017809 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017810 * Resolve identity-constraint keyRefs.
17811 */
17812 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017813 /*
17814 * Check type defnitions for circular references.
17815 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017816 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017817 xmlSchemaCheckTypeDefCircular, ctxt);
17818 /*
17819 * Check model groups defnitions for circular references.
17820 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017821 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017822 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017823 /*
17824 * Set the "term" of particles pointing to model group definitions
17825 * to the contained model group.
17826 */
17827 if (ret->volatiles != NULL) {
17828 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17829 int i;
17830 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017831
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017832 for (i = 0; i < list->nbItems; i++) {
17833 item = (xmlSchemaParticlePtr) list->items[i];
17834 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17835 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17836 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017837 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017838 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017839 * Check attribute groups for circular references.
17840 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017841 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17842 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017843 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017844 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017845 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017846 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017847 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017848 /*
17849 * We will stop here if the schema was not valid to avoid internal errors
17850 * on missing sub-components. This is not conforming to the spec, since it
17851 * allows missing components, but it might make further processing crash.
17852 * So see it as a very strict handling, which might be made more lax in the
17853 * future.
17854 */
17855 if (ctxt->nberrors != 0)
17856 goto exit;
17857 /*
17858 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017859 */
17860 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017861 /*
17862 * Validate the value constraint of attribute declarations/uses.
17863 */
17864 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017865 /*
17866 * Validate the value constraint of element declarations.
17867 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017868 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017869
17870 if (ctxt->nberrors != 0)
17871 goto exit;
17872
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017873 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017874 * TODO: cos-element-consistent, cos-all-limited
17875 *
17876 * Then build the content model for all complex types
17877 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017878 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017879 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017880
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017881exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017882 if (ctxt->nberrors != 0) {
17883 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017884 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017885 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017886 return (ret);
17887}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017888
Daniel Veillard4255d502002-04-16 15:50:10 +000017889/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017890 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017891 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017892 * @err: the error callback
17893 * @warn: the warning callback
17894 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017895 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017896 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017897 */
17898void
17899xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017900 xmlSchemaValidityErrorFunc err,
17901 xmlSchemaValidityWarningFunc warn, void *ctx)
17902{
Daniel Veillard4255d502002-04-16 15:50:10 +000017903 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017904 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017905 ctxt->error = err;
17906 ctxt->warning = warn;
17907 ctxt->userData = ctx;
17908}
17909
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017910/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017911 * xmlSchemaGetParserErrors:
17912 * @ctxt: a XMl-Schema parser context
17913 * @err: the error callback result
17914 * @warn: the warning callback result
17915 * @ctx: contextual data for the callbacks result
17916 *
17917 * Get the callback information used to handle errors for a parser context
17918 *
17919 * Returns -1 in case of failure, 0 otherwise
17920 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017921int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017922xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17923 xmlSchemaValidityErrorFunc * err,
17924 xmlSchemaValidityWarningFunc * warn, void **ctx)
17925{
17926 if (ctxt == NULL)
17927 return(-1);
17928 if (err != NULL)
17929 *err = ctxt->error;
17930 if (warn != NULL)
17931 *warn = ctxt->warning;
17932 if (ctx != NULL)
17933 *ctx = ctxt->userData;
17934 return(0);
17935}
17936
17937/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017938 * xmlSchemaFacetTypeToString:
17939 * @type: the facet type
17940 *
17941 * Convert the xmlSchemaTypeType to a char string.
17942 *
17943 * Returns the char string representation of the facet type if the
17944 * type is a facet and an "Internal Error" string otherwise.
17945 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017946static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017947xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17948{
17949 switch (type) {
17950 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017951 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017952 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017953 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017954 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017955 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017956 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017957 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017958 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017959 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017960 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017961 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017962 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017963 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017964 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017965 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017966 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017967 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017968 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017969 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017970 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017971 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017972 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017973 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017974 default:
17975 break;
17976 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017977 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017978}
17979
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017980static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017981xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17982{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017983 /*
17984 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017985 * from xsd:string.
17986 */
17987 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017988 /*
17989 * Note that we assume a whitespace of preserve for anySimpleType.
17990 */
17991 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17992 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17993 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017994 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017995 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017996 else {
17997 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017998 * For all ·atomic· datatypes other than string (and types ·derived·
17999 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000018000 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018001 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018003 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018004 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018005 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018006 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018007 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018008 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018009 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
18010 } else if (VARIETY_UNION(type)) {
18011 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
18012 } else if (VARIETY_ATOMIC(type)) {
18013 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
18014 return (XML_SCHEMA_WHITESPACE_PRESERVE);
18015 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
18016 return (XML_SCHEMA_WHITESPACE_REPLACE);
18017 else
18018 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018019 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018020 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018021}
18022
Daniel Veillard4255d502002-04-16 15:50:10 +000018023/************************************************************************
18024 * *
18025 * Simple type validation *
18026 * *
18027 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018028
Daniel Veillard4255d502002-04-16 15:50:10 +000018029
18030/************************************************************************
18031 * *
18032 * DOM Validation code *
18033 * *
18034 ************************************************************************/
18035
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018036static void
18037xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18038{
18039 int i, nbItems;
18040 xmlSchemaTypePtr item, *items;
18041
18042
18043 /*
18044 * During the Assemble of the schema ctxt->curItems has
18045 * been filled with the relevant new items. Fix those up.
18046 */
18047 nbItems = ctxt->assemble->nbItems;
18048 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018049
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018050 for (i = 0; i < nbItems; i++) {
18051 item = items[i];
18052 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018053 case XML_SCHEMA_TYPE_COMPLEX:
18054 case XML_SCHEMA_TYPE_SIMPLE:
18055 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18056 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018057 case XML_SCHEMA_TYPE_ATTRIBUTE:
18058 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18059 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018060 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018061 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018062 ctxt, NULL);
18063 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018064 case XML_SCHEMA_TYPE_PARTICLE:
18065 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018066 break;
18067 case XML_SCHEMA_TYPE_IDC_KEY:
18068 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18069 case XML_SCHEMA_TYPE_IDC_KEYREF:
18070 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18071 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018072 default:
18073 break;
18074 }
18075 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018076 if (ctxt->nberrors != 0)
18077 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018078 /*
18079 * Circularity checks.
18080 */
18081 for (i = 0; i < nbItems; i++) {
18082 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018083 switch (item->type) {
18084 case XML_SCHEMA_TYPE_COMPLEX:
18085 case XML_SCHEMA_TYPE_SIMPLE:
18086 xmlSchemaCheckTypeDefCircular(
18087 (xmlSchemaTypePtr) item, ctxt, NULL);
18088 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018089 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018090 xmlSchemaCheckGroupDefCircular(
18091 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018092 break;
18093 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18094 xmlSchemaCheckAttributeGroupCircular(
18095 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18096 break;
18097 default:
18098 break;
18099 }
18100 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018101 if (ctxt->nberrors != 0)
18102 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018103 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018104 * Set the "term" of particles pointing to model group definitions
18105 * to the contained model group.
18106 */
18107 for (i = 0; i < nbItems; i++) {
18108 item = items[i];
18109 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18110 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018111 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018112 XML_SCHEMA_TYPE_GROUP)) {
18113 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18114 ctxt, NULL);
18115 }
18116 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018117 if (ctxt->nberrors != 0)
18118 return;
18119 for (i = 0; i < nbItems; i++) {
18120 item = items[i];
18121 switch (item->type) {
18122 case XML_SCHEMA_TYPE_ELEMENT:
18123 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18124 NULL, NULL, NULL);
18125 break;
18126 default:
18127 break;
18128 }
18129 }
18130 if (ctxt->nberrors != 0)
18131 return;
18132
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018133 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018134 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018135 */
18136 for (i = 0; i < nbItems; i++) {
18137 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018138 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018139 case XML_SCHEMA_TYPE_SIMPLE:
18140 case XML_SCHEMA_TYPE_COMPLEX:
18141 xmlSchemaTypeFixup(item, ctxt, NULL);
18142 break;
18143 default:
18144 break;
18145 }
18146 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018147 if (ctxt->nberrors != 0)
18148 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018149 /*
18150 * Validate value contraint values.
18151 */
18152 for (i = 0; i < nbItems; i++) {
18153 item = items[i];
18154 switch (item->type) {
18155 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018156 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18157 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018158 break;
18159 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018160 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018161 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018162 break;
18163 default:
18164 break;
18165 }
18166 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018167 if (ctxt->nberrors != 0)
18168 return;
18169 /*
18170 * Build the content model for complex types.
18171 */
18172 for (i = 0; i < nbItems; i++) {
18173 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018174 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018175 case XML_SCHEMA_TYPE_COMPLEX:
18176 xmlSchemaBuildContentModel(item, ctxt, NULL);
18177 break;
18178 default:
18179 break;
18180 }
18181 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018182}
18183
18184/**
18185 * xmlSchemaAssembleByLocation:
18186 * @pctxt: a schema parser context
18187 * @vctxt: a schema validation context
18188 * @schema: the existing schema
18189 * @node: the node that fired the assembling
18190 * @nsName: the namespace name of the new schema
18191 * @location: the location of the schema
18192 *
18193 * Expands an existing schema by an additional schema.
18194 *
18195 * Returns 0 if the new schema is correct, a positive error code
18196 * number otherwise and -1 in case of an internal or API error.
18197 */
18198static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018199xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018200 xmlSchemaPtr schema,
18201 xmlNodePtr node,
18202 const xmlChar *nsName,
18203 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018204{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018205 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018206 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018207 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018208 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018209 xmlSchemaParserCtxtPtr pctxt;
18210
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018211 /*
18212 * This should be used:
18213 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018214 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018215 * 3. if requested via the API
18216 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018217 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018218 return (-1);
18219 /*
18220 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018221 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018222 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018223 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18224 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018225 pctxt = vctxt->pctxt;
18226 /*
18227 * Set the counter to produce unique names for anonymous items.
18228 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018229 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018230 /*
18231 * Acquire the schema document.
18232 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018233 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18234 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018235 if (ret != 0) {
18236 if (doc != NULL)
18237 xmlFreeDoc(doc);
18238 } else if (doc != NULL) {
18239 docElem = xmlDocGetRootElement(doc);
18240 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018241 * Create new assemble info.
18242 */
18243 if (pctxt->assemble == NULL) {
18244 pctxt->assemble = xmlSchemaNewAssemble();
18245 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018246 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018247 "Memory error: xmlSchemaAssembleByLocation, "
18248 "allocating assemble info", NULL);
18249 xmlFreeDoc(doc);
18250 return (-1);
18251 }
18252 }
18253 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018254 * Save and reset the context & schema.
18255 */
18256 oldflags = schema->flags;
18257 oldtns = schema->targetNamespace;
18258 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018259 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018260
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018261 xmlSchemaClearSchemaDefaults(schema);
18262 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018263 if ((targetNs != NULL) &&
18264 xmlStrEqual(targetNs, xmlSchemaNs)) {
18265 /*
18266 * We are parsing the schema for schema!
18267 */
18268 vctxt->pctxt->isS4S = 1;
18269 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018270 /* schema->nbCurItems = 0; */
18271 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018272 pctxt->ctxtType = NULL;
18273 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018274
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018275 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18276 if (pctxt->nberrors != 0) {
18277 vctxt->nberrors += pctxt->nberrors;
18278 goto finally;
18279 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018280 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018281 if (pctxt->nberrors != 0) {
18282 vctxt->nberrors += pctxt->nberrors;
18283 goto finally;
18284 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018285 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018286 if (pctxt->nberrors != 0)
18287 vctxt->nberrors += pctxt->nberrors;
18288finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018289 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018290 * Set the counter of items.
18291 */
18292 schema->counter = pctxt->counter;
18293 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018294 * Free the list of assembled components.
18295 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018296 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018297 /*
18298 * Restore the context & schema.
18299 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018300 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018301 schema->flags = oldflags;
18302 schema->targetNamespace = oldtns;
18303 schema->doc = olddoc;
18304 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018305 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018306 return (ret);
18307}
18308
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018309static xmlSchemaAttrInfoPtr
18310xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18311 int metaType)
18312{
18313 if (vctxt->nbAttrInfos == 0)
18314 return (NULL);
18315 {
18316 int i;
18317 xmlSchemaAttrInfoPtr iattr;
18318
18319 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18320 iattr = vctxt->attrInfos[i];
18321 if (iattr->metaType == metaType)
18322 return (iattr);
18323 }
18324
18325 }
18326 return (NULL);
18327}
18328
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018329/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018330 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018331 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018332 *
18333 * Expands an existing schema by an additional schema using
18334 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18335 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18336 * must be set to 1.
18337 *
18338 * Returns 0 if the new schema is correct, a positive error code
18339 * number otherwise and -1 in case of an internal or API error.
18340 */
18341static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018342xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018343{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018344 const xmlChar *cur, *end;
18345 const xmlChar *nsname = NULL, *location;
18346 int count = 0;
18347 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018348 xmlSchemaAttrInfoPtr iattr;
18349
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018350 /*
18351 * Parse the value; we will assume an even number of values
18352 * to be given (this is how Xerces and XSV work).
18353 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018354 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18355 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18356 if (iattr == NULL)
18357 xmlSchemaGetMetaAttrInfo(vctxt,
18358 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18359 if (iattr == NULL)
18360 return (0);
18361 cur = iattr->value;
18362 do {
18363 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018364 /*
18365 * Get the namespace name.
18366 */
18367 while (IS_BLANK_CH(*cur))
18368 cur++;
18369 end = cur;
18370 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18371 end++;
18372 if (end == cur)
18373 break;
18374 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018375 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018376 cur = end;
18377 }
18378 /*
18379 * Get the URI.
18380 */
18381 while (IS_BLANK_CH(*cur))
18382 cur++;
18383 end = cur;
18384 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18385 end++;
18386 if (end == cur)
18387 break;
18388 count++;
18389 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018390 cur = end;
18391 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18392 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018393 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018394 VERROR_INT("xmlSchemaAssembleByXSI",
18395 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018396 return (-1);
18397 }
18398 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018399 return (ret);
18400}
18401
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018402#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018403
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018404static const xmlChar *
18405xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18406 const xmlChar *prefix)
18407{
18408 if (vctxt->sax != NULL) {
18409 int i, j;
18410 xmlSchemaNodeInfoPtr inode;
18411
18412 for (i = vctxt->depth; i >= 0; i--) {
18413 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18414 inode = vctxt->elemInfos[i];
18415 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18416 if (((prefix == NULL) &&
18417 (inode->nsBindings[j] == NULL)) ||
18418 ((prefix != NULL) && xmlStrEqual(prefix,
18419 inode->nsBindings[j]))) {
18420
18421 /*
18422 * Note that the namespace bindings are already
18423 * in a string dict.
18424 */
18425 return (inode->nsBindings[j+1]);
18426 }
18427 }
18428 }
18429 }
18430 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018431#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018432 } else if (vctxt->reader != NULL) {
18433 xmlChar *nsName;
18434
18435 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18436 if (nsName != NULL) {
18437 const xmlChar *ret;
18438
18439 VAL_CREATE_DICT;
18440 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18441 xmlFree(nsName);
18442 return (ret);
18443 } else
18444 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018445#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018446 } else {
18447 xmlNsPtr ns;
18448
18449 if ((vctxt->inode->node == NULL) ||
18450 (vctxt->inode->node->doc == NULL)) {
18451 VERROR_INT("xmlSchemaLookupNamespace",
18452 "no node or node's doc avaliable");
18453 return (NULL);
18454 }
18455 ns = xmlSearchNs(vctxt->inode->node->doc,
18456 vctxt->inode->node, prefix);
18457 if (ns != NULL)
18458 return (ns->href);
18459 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018460 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018461}
18462
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018463/*
18464* This one works on the schema of the validation context.
18465*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018466static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018467xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18468 xmlSchemaPtr schema,
18469 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018470 const xmlChar *value,
18471 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018472 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018473{
18474 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018475
18476 if (vctxt && (vctxt->schema == NULL)) {
18477 VERROR_INT("xmlSchemaValidateNotation",
18478 "a schema is needed on the validation context");
18479 return (-1);
18480 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018481 ret = xmlValidateQName(value, 1);
18482 if (ret != 0)
18483 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018484 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018485 xmlChar *localName = NULL;
18486 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018487
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018488 localName = xmlSplitQName2(value, &prefix);
18489 if (prefix != NULL) {
18490 const xmlChar *nsName = NULL;
18491
18492 if (vctxt != NULL)
18493 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18494 else if (node != NULL) {
18495 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18496 if (ns != NULL)
18497 nsName = ns->href;
18498 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018499 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018500 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018501 return (1);
18502 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018503 if (nsName == NULL) {
18504 xmlFree(prefix);
18505 xmlFree(localName);
18506 return (1);
18507 }
18508 if (xmlHashLookup2(schema->notaDecl, localName,
18509 nsName) != NULL) {
18510 if (valNeeded && (val != NULL)) {
18511 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18512 BAD_CAST xmlStrdup(nsName));
18513 if (*val == NULL)
18514 ret = -1;
18515 }
18516 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018517 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018518 xmlFree(prefix);
18519 xmlFree(localName);
18520 } else {
18521 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18522 if (valNeeded && (val != NULL)) {
18523 (*val) = xmlSchemaNewNOTATIONValue(
18524 BAD_CAST xmlStrdup(value), NULL);
18525 if (*val == NULL)
18526 ret = -1;
18527 }
18528 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018529 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018530 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018531 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018532 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018533}
18534
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018535/************************************************************************
18536 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018537 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018538 * *
18539 ************************************************************************/
18540
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018541/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018542 * xmlSchemaAugmentIDC:
18543 * @idcDef: the IDC definition
18544 *
18545 * Creates an augmented IDC definition item.
18546 *
18547 * Returns the item, or NULL on internal errors.
18548 */
18549static void
18550xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18551 xmlSchemaValidCtxtPtr vctxt)
18552{
18553 xmlSchemaIDCAugPtr aidc;
18554
18555 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18556 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018557 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018558 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18559 NULL);
18560 return;
18561 }
18562 aidc->bubbleDepth = -1;
18563 aidc->def = idcDef;
18564 aidc->next = NULL;
18565 if (vctxt->aidcs == NULL)
18566 vctxt->aidcs = aidc;
18567 else {
18568 aidc->next = vctxt->aidcs;
18569 vctxt->aidcs = aidc;
18570 }
18571}
18572
18573/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018574 * xmlSchemaIDCNewBinding:
18575 * @idcDef: the IDC definition of this binding
18576 *
18577 * Creates a new IDC binding.
18578 *
18579 * Returns the new binding in case of succeeded, NULL on internal errors.
18580 */
18581static xmlSchemaPSVIIDCBindingPtr
18582xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18583{
18584 xmlSchemaPSVIIDCBindingPtr ret;
18585
18586 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18587 sizeof(xmlSchemaPSVIIDCBinding));
18588 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018589 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018590 "allocating a PSVI IDC binding item", NULL);
18591 return (NULL);
18592 }
18593 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18594 ret->definition = idcDef;
18595 return (ret);
18596}
18597
18598/**
18599 * xmlSchemaIDCStoreNodeTableItem:
18600 * @vctxt: the WXS validation context
18601 * @item: the IDC node table item
18602 *
18603 * The validation context is used to store an IDC node table items.
18604 * They are stored to avoid copying them if IDC node-tables are merged
18605 * with corresponding parent IDC node-tables (bubbling).
18606 *
18607 * Returns 0 if succeeded, -1 on internal errors.
18608 */
18609static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018610xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018611 xmlSchemaPSVIIDCNodePtr item)
18612{
18613 /*
18614 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018615 */
18616 if (vctxt->idcNodes == NULL) {
18617 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018618 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18619 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018620 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018621 "allocating the IDC node table item list", NULL);
18622 return (-1);
18623 }
18624 vctxt->sizeIdcNodes = 20;
18625 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18626 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018627 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18628 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018629 sizeof(xmlSchemaPSVIIDCNodePtr));
18630 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018631 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018632 "re-allocating the IDC node table item list", NULL);
18633 return (-1);
18634 }
18635 }
18636 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018637
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018638 return (0);
18639}
18640
18641/**
18642 * xmlSchemaIDCStoreKey:
18643 * @vctxt: the WXS validation context
18644 * @item: the IDC key
18645 *
18646 * The validation context is used to store an IDC key.
18647 *
18648 * Returns 0 if succeeded, -1 on internal errors.
18649 */
18650static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018651xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018652 xmlSchemaPSVIIDCKeyPtr key)
18653{
18654 /*
18655 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018656 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018657 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018658 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018659 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18660 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018661 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018662 "allocating the IDC key storage list", NULL);
18663 return (-1);
18664 }
18665 vctxt->sizeIdcKeys = 40;
18666 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18667 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018668 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18669 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018670 sizeof(xmlSchemaPSVIIDCKeyPtr));
18671 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018672 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018673 "re-allocating the IDC key storage list", NULL);
18674 return (-1);
18675 }
18676 }
18677 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018678
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018679 return (0);
18680}
18681
18682/**
18683 * xmlSchemaIDCAppendNodeTableItem:
18684 * @bind: the IDC binding
18685 * @ntItem: the node-table item
18686 *
18687 * Appends the IDC node-table item to the binding.
18688 *
18689 * Returns 0 on success and -1 on internal errors.
18690 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018691static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018692xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18693 xmlSchemaPSVIIDCNodePtr ntItem)
18694{
18695 if (bind->nodeTable == NULL) {
18696 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018697 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018698 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18699 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018700 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018701 "allocating an array of IDC node-table items", NULL);
18702 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018703 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018704 } else if (bind->sizeNodes <= bind->nbNodes) {
18705 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018706 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18707 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018708 sizeof(xmlSchemaPSVIIDCNodePtr));
18709 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018710 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018711 "re-allocating an array of IDC node-table items", NULL);
18712 return(-1);
18713 }
18714 }
18715 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018716 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018717}
18718
18719/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018720 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018721 * @vctxt: the WXS validation context
18722 * @matcher: the IDC matcher
18723 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018724 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018725 * of the given matcher. If none found, a new one is created
18726 * and added to the IDC table.
18727 *
18728 * Returns an IDC binding or NULL on internal errors.
18729 */
18730static xmlSchemaPSVIIDCBindingPtr
18731xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18732 xmlSchemaIDCMatcherPtr matcher)
18733{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018734 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018735
18736 info = vctxt->elemInfos[matcher->depth];
18737
18738 if (info->idcTable == NULL) {
18739 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18740 if (info->idcTable == NULL)
18741 return (NULL);
18742 return(info->idcTable);
18743 } else {
18744 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018745
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018746 bind = info->idcTable;
18747 do {
18748 if (bind->definition == matcher->aidc->def)
18749 return(bind);
18750 if (bind->next == NULL) {
18751 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18752 if (bind->next == NULL)
18753 return (NULL);
18754 return(bind->next);
18755 }
18756 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018757 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018758 }
18759 return (NULL);
18760}
18761
18762/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018763 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018764 * @key: the IDC key
18765 *
18766 * Frees an IDC key together with its compiled value.
18767 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018768static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018769xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18770{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018771 if (key->val != NULL)
18772 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018773 xmlFree(key);
18774}
18775
18776/**
18777 * xmlSchemaIDCFreeBinding:
18778 *
18779 * Frees an IDC binding. Note that the node table-items
18780 * are not freed.
18781 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018782static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018783xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18784{
18785 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018786 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18787 int i;
18788 /*
18789 * Node-table items for keyrefs are not stored globally
18790 * to the validation context, since they are not bubbled.
18791 * We need to free them here.
18792 */
18793 for (i = 0; i < bind->nbNodes; i++) {
18794 xmlFree(bind->nodeTable[i]->keys);
18795 xmlFree(bind->nodeTable[i]);
18796 }
18797 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018798 xmlFree(bind->nodeTable);
18799 }
18800 xmlFree(bind);
18801}
18802
18803/**
18804 * xmlSchemaIDCFreeIDCTable:
18805 * @bind: the first IDC binding in the list
18806 *
18807 * Frees an IDC table, i.e. all the IDC bindings in the list.
18808 */
18809static void
18810xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18811{
18812 xmlSchemaPSVIIDCBindingPtr prev;
18813
18814 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018815 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018816 bind = bind->next;
18817 xmlSchemaIDCFreeBinding(prev);
18818 }
18819}
18820
18821/**
18822 * xmlSchemaIDCFreeMatcherList:
18823 * @matcher: the first IDC matcher in the list
18824 *
18825 * Frees a list of IDC matchers.
18826 */
18827static void
18828xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18829{
18830 xmlSchemaIDCMatcherPtr next;
18831
18832 while (matcher != NULL) {
18833 next = matcher->next;
18834 if (matcher->keySeqs != NULL) {
18835 int i;
18836 for (i = 0; i < matcher->sizeKeySeqs; i++)
18837 if (matcher->keySeqs[i] != NULL)
18838 xmlFree(matcher->keySeqs[i]);
18839 xmlFree(matcher->keySeqs);
18840 }
18841 xmlFree(matcher);
18842 matcher = next;
18843 }
18844}
18845
18846/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018847 * xmlSchemaIDCAddStateObject:
18848 * @vctxt: the WXS validation context
18849 * @matcher: the IDC matcher
18850 * @sel: the XPath information
18851 * @parent: the parent "selector" state object if any
18852 * @type: "selector" or "field"
18853 *
18854 * Creates/reuses and activates state objects for the given
18855 * XPath information; if the XPath expression consists of unions,
18856 * multiple state objects are created for every unioned expression.
18857 *
18858 * Returns 0 on success and -1 on internal errors.
18859 */
18860static int
18861xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18862 xmlSchemaIDCMatcherPtr matcher,
18863 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018864 int type)
18865{
18866 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018867
18868 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018869 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018870 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018871 if (vctxt->xpathStatePool != NULL) {
18872 sto = vctxt->xpathStatePool;
18873 vctxt->xpathStatePool = sto->next;
18874 sto->next = NULL;
18875 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018876 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018877 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018878 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018879 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18880 if (sto == NULL) {
18881 xmlSchemaVErrMemory(NULL,
18882 "allocating an IDC state object", NULL);
18883 return (-1);
18884 }
18885 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18886 }
18887 /*
18888 * Add to global list.
18889 */
18890 if (vctxt->xpathStates != NULL)
18891 sto->next = vctxt->xpathStates;
18892 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018893
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018894 /*
18895 * Free the old xpath validation context.
18896 */
18897 if (sto->xpathCtxt != NULL)
18898 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18899
18900 /*
18901 * Create a new XPath (pattern) validation context.
18902 */
18903 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18904 (xmlPatternPtr) sel->xpathComp);
18905 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018906 VERROR_INT("xmlSchemaIDCAddStateObject",
18907 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018908 return (-1);
18909 }
18910 sto->type = type;
18911 sto->depth = vctxt->depth;
18912 sto->matcher = matcher;
18913 sto->sel = sel;
18914 sto->nbHistory = 0;
18915
18916#if DEBUG_IDC
18917 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18918 sto->sel->xpath);
18919#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018920 return (0);
18921}
18922
18923/**
18924 * xmlSchemaXPathEvaluate:
18925 * @vctxt: the WXS validation context
18926 * @nodeType: the nodeType of the current node
18927 *
18928 * Evaluates all active XPath state objects.
18929 *
18930 * Returns the number of IC "field" state objects which resolved to
18931 * this node, 0 if none resolved and -1 on internal errors.
18932 */
18933static int
18934xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018935 xmlElementType nodeType)
18936{
18937 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018938 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018939
18940 if (vctxt->xpathStates == NULL)
18941 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018942
18943 if (nodeType == XML_ATTRIBUTE_NODE)
18944 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018945#if DEBUG_IDC
18946 {
18947 xmlChar *str = NULL;
18948 xmlGenericError(xmlGenericErrorContext,
18949 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018950 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18951 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018952 FREE_AND_NULL(str)
18953 }
18954#endif
18955 /*
18956 * Process all active XPath state objects.
18957 */
18958 first = vctxt->xpathStates;
18959 sto = first;
18960 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018961#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018962 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018963 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18964 sto->matcher->aidc->def->name, sto->sel->xpath);
18965 else
18966 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18967 sto->matcher->aidc->def->name, sto->sel->xpath);
18968#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018969 if (nodeType == XML_ELEMENT_NODE)
18970 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018971 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018972 else
18973 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018974 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018975
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018976 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018977 VERROR_INT("xmlSchemaXPathEvaluate",
18978 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018979 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018980 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018981 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018982 goto next_sto;
18983 /*
18984 * Full match.
18985 */
18986#if DEBUG_IDC
18987 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018988 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018989#endif
18990 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018991 * Register a match in the state object history.
18992 */
18993 if (sto->history == NULL) {
18994 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18995 if (sto->history == NULL) {
18996 xmlSchemaVErrMemory(NULL,
18997 "allocating the state object history", NULL);
18998 return(-1);
18999 }
19000 sto->sizeHistory = 10;
19001 } else if (sto->sizeHistory <= sto->nbHistory) {
19002 sto->sizeHistory *= 2;
19003 sto->history = (int *) xmlRealloc(sto->history,
19004 sto->sizeHistory * sizeof(int));
19005 if (sto->history == NULL) {
19006 xmlSchemaVErrMemory(NULL,
19007 "re-allocating the state object history", NULL);
19008 return(-1);
19009 }
19010 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019011 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019012
19013#ifdef DEBUG_IDC
19014 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19015 vctxt->depth);
19016#endif
19017
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019018 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19019 xmlSchemaIDCSelectPtr sel;
19020 /*
19021 * Activate state objects for the IDC fields of
19022 * the IDC selector.
19023 */
19024#if DEBUG_IDC
19025 xmlGenericError(xmlGenericErrorContext, "IDC: "
19026 "activating field states\n");
19027#endif
19028 sel = sto->matcher->aidc->def->fields;
19029 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019030 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19031 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19032 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019033 sel = sel->next;
19034 }
19035 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19036 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019037 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019038 */
19039#if DEBUG_IDC
19040 xmlGenericError(xmlGenericErrorContext,
19041 "IDC: key found\n");
19042#endif
19043 /*
19044 * Notify that the character value of this node is
19045 * needed.
19046 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019047 if (resolved == 0) {
19048 if ((vctxt->inode->flags &
19049 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19050 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19051 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019052 resolved++;
19053 }
19054next_sto:
19055 if (sto->next == NULL) {
19056 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019057 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019058 */
19059 head = first;
19060 sto = vctxt->xpathStates;
19061 } else
19062 sto = sto->next;
19063 }
19064 return (resolved);
19065}
19066
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019067static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019068xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019069 xmlChar **buf,
19070 xmlSchemaPSVIIDCKeyPtr *seq,
19071 int count)
19072{
19073 int i, res;
19074 const xmlChar *value = NULL;
19075
19076 *buf = xmlStrdup(BAD_CAST "[");
19077 for (i = 0; i < count; i++) {
19078 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019079 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19080 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019081 if (res == 0)
19082 *buf = xmlStrcat(*buf, value);
19083 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019084 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19085 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019086 *buf = xmlStrcat(*buf, BAD_CAST "???");
19087 }
19088 if (i < count -1)
19089 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19090 else
19091 *buf = xmlStrcat(*buf, BAD_CAST "'");
19092 if (value != NULL) {
19093 xmlFree((xmlChar *) value);
19094 value = NULL;
19095 }
19096 }
19097 *buf = xmlStrcat(*buf, BAD_CAST "]");
19098
19099 return (BAD_CAST *buf);
19100}
19101
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019102/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019103 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019104 * @vctxt: the WXS validation context
19105 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019106 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019107 *
19108 * Processes and pops the history items of the IDC state objects.
19109 * IDC key-sequences are validated/created on IDC bindings.
19110 *
19111 * Returns 0 on success and -1 on internal errors.
19112 */
19113static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019114xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019115 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019116{
19117 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019118 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019119 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019120 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019121
19122 if (vctxt->xpathStates == NULL)
19123 return (0);
19124 sto = vctxt->xpathStates;
19125
19126#if DEBUG_IDC
19127 {
19128 xmlChar *str = NULL;
19129 xmlGenericError(xmlGenericErrorContext,
19130 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019131 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19132 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019133 FREE_AND_NULL(str)
19134 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019135#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019136 /*
19137 * Evaluate the state objects.
19138 */
19139 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019140 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19141 if (res == -1) {
19142 VERROR_INT("xmlSchemaXPathProcessHistory",
19143 "calling xmlStreamPop()");
19144 return (-1);
19145 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019146#if DEBUG_IDC
19147 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19148 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019149#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019150 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019151 goto deregister_check;
19152
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019153 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019154
19155 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019156 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019157 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019158 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019159 sto = sto->next;
19160 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019161 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019162 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19163 if (! IS_SIMPLE_TYPE(type)) {
19164 /*
19165 * Not qualified if the field resolves to a node of non
19166 * simple type.
19167 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019168 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19169 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019170 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19171 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019172 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019173
19174 sto->nbHistory--;
19175 goto deregister_check;
19176 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019177 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019178 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019179 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019180 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019181 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019182 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019183 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19184 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019185 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019186 sto->nbHistory--;
19187 goto deregister_check;
19188 } else {
19189 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19190 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019191 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019192
19193 /*
19194 * The key will be anchored on the matcher's list of
19195 * key-sequences. The position in this list is determined
19196 * by the target node's depth relative to the matcher's
19197 * depth of creation (i.e. the depth of the scope element).
19198 */
19199 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019200 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019201
19202 /*
19203 * Create/grow the array of key-sequences.
19204 */
19205 if (matcher->keySeqs == NULL) {
19206 if (pos > 9)
19207 matcher->sizeKeySeqs = pos * 2;
19208 else
19209 matcher->sizeKeySeqs = 10;
19210 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19211 xmlMalloc(matcher->sizeKeySeqs *
19212 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19213 if (matcher->keySeqs == NULL) {
19214 xmlSchemaVErrMemory(NULL,
19215 "allocating an array of key-sequences",
19216 NULL);
19217 return(-1);
19218 }
19219 memset(matcher->keySeqs, 0,
19220 matcher->sizeKeySeqs *
19221 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19222 } else if (pos >= matcher->sizeKeySeqs) {
19223 int i = matcher->sizeKeySeqs;
19224
19225 matcher->sizeKeySeqs *= 2;
19226 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19227 xmlRealloc(matcher->keySeqs,
19228 matcher->sizeKeySeqs *
19229 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019230 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019231 xmlSchemaVErrMemory(NULL,
19232 "reallocating an array of key-sequences",
19233 NULL);
19234 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019235 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019236 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019237 * The array needs to be NULLed.
19238 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019239 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019240 for (; i < matcher->sizeKeySeqs; i++)
19241 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019242 }
19243
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019244 /*
19245 * Get/create the key-sequence.
19246 */
19247 keySeq = matcher->keySeqs[pos];
19248 if (keySeq == NULL) {
19249 goto create_sequence;
19250 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019251 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019252 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019253 * cvc-identity-constraint:
19254 * 3 For each node in the ·target node set· all
19255 * of the {fields}, with that node as the context
19256 * node, evaluate to either an empty node-set or
19257 * a node-set with exactly one member, which must
19258 * have a simple type.
19259 *
19260 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019261 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019262 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19263 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019264 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019265 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019266 "with more than one member",
19267 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019268 sto->nbHistory--;
19269 goto deregister_check;
19270 } else {
19271 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019272 }
19273 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019274
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019275create_sequence:
19276 /*
19277 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019278 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019279 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19280 matcher->aidc->def->nbFields *
19281 sizeof(xmlSchemaPSVIIDCKeyPtr));
19282 if (keySeq == NULL) {
19283 xmlSchemaVErrMemory(NULL,
19284 "allocating an IDC key-sequence", NULL);
19285 return(-1);
19286 }
19287 memset(keySeq, 0, matcher->aidc->def->nbFields *
19288 sizeof(xmlSchemaPSVIIDCKeyPtr));
19289 matcher->keySeqs[pos] = keySeq;
19290create_key:
19291 /*
19292 * Created a key once per node only.
19293 */
19294 if (key == NULL) {
19295 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19296 sizeof(xmlSchemaPSVIIDCKey));
19297 if (key == NULL) {
19298 xmlSchemaVErrMemory(NULL,
19299 "allocating a IDC key", NULL);
19300 xmlFree(keySeq);
19301 matcher->keySeqs[pos] = NULL;
19302 return(-1);
19303 }
19304 /*
19305 * Consume the compiled value.
19306 */
19307 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019308 key->val = vctxt->inode->val;
19309 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019310 /*
19311 * Store the key in a global list.
19312 */
19313 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19314 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019315 return (-1);
19316 }
19317 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019318 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019319 }
19320 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019321
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019322 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19323 xmlSchemaPSVIIDCBindingPtr bind;
19324 xmlSchemaPSVIIDCNodePtr ntItem;
19325 xmlSchemaIDCMatcherPtr matcher;
19326 xmlSchemaIDCPtr idc;
19327 int pos, i, j, nbKeys;
19328 /*
19329 * Here we have the following scenario:
19330 * An IDC 'selector' state object resolved to a target node,
19331 * during the time this target node was in the
19332 * ancestor-or-self axis, the 'field' state object(s) looked
19333 * out for matching nodes to create a key-sequence for this
19334 * target node. Now we are back to this target node and need
19335 * to put the key-sequence, together with the target node
19336 * itself, into the node-table of the corresponding IDC
19337 * binding.
19338 */
19339 matcher = sto->matcher;
19340 idc = matcher->aidc->def;
19341 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019342 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019343 /*
19344 * Check if the matcher has any key-sequences at all, plus
19345 * if it has a key-sequence for the current target node.
19346 */
19347 if ((matcher->keySeqs == NULL) ||
19348 (matcher->sizeKeySeqs <= pos)) {
19349 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19350 goto selector_key_error;
19351 else
19352 goto selector_leave;
19353 }
19354
19355 keySeq = &(matcher->keySeqs[pos]);
19356 if (*keySeq == NULL) {
19357 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19358 goto selector_key_error;
19359 else
19360 goto selector_leave;
19361 }
19362
19363 for (i = 0; i < nbKeys; i++) {
19364 if ((*keySeq)[i] == NULL) {
19365 /*
19366 * Not qualified, if not all fields did resolve.
19367 */
19368 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19369 /*
19370 * All fields of a "key" IDC must resolve.
19371 */
19372 goto selector_key_error;
19373 }
19374 goto selector_leave;
19375 }
19376 }
19377 /*
19378 * All fields did resolve.
19379 */
19380
19381 /*
19382 * 4.1 If the {identity-constraint category} is unique(/key),
19383 * then no two members of the ·qualified node set· have
19384 * ·key-sequences· whose members are pairwise equal, as
19385 * defined by Equal in [XML Schemas: Datatypes].
19386 *
19387 * Get the IDC binding from the matcher and check for
19388 * duplicate key-sequences.
19389 */
19390 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19391 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19392 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019393 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019394
19395 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019396 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019397 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019398 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019399 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019400 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019401 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019402 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019403 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019404 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019405 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019406 if (res == -1) {
19407 return (-1);
19408 } else if (res == 0)
19409 break;
19410 }
19411 if (res == 1) {
19412 /*
19413 * Duplicate found.
19414 */
19415 break;
19416 }
19417 i++;
19418 } while (i < bind->nbNodes);
19419 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019420 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019421 /*
19422 * TODO: Try to report the key-sequence.
19423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019424 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19425 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019426 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019427 "Duplicate key-sequence %s",
19428 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19429 (*keySeq), nbKeys), NULL);
19430 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019431 goto selector_leave;
19432 }
19433 }
19434 /*
19435 * Add a node-table item to the IDC binding.
19436 */
19437 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19438 sizeof(xmlSchemaPSVIIDCNode));
19439 if (ntItem == NULL) {
19440 xmlSchemaVErrMemory(NULL,
19441 "allocating an IDC node-table item", NULL);
19442 xmlFree(*keySeq);
19443 *keySeq = NULL;
19444 return(-1);
19445 }
19446 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19447
19448 /*
19449 * Store the node-table item on global list.
19450 */
19451 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19452 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19453 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019454 xmlFree(*keySeq);
19455 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019456 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019457 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019458 }
19459 /*
19460 * Init the node-table item. Consume the key-sequence.
19461 */
19462 ntItem->node = vctxt->node;
19463 ntItem->keys = *keySeq;
19464 *keySeq = NULL;
19465 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19466 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19467 /*
19468 * Free the item, since keyref items won't be
19469 * put on a global list.
19470 */
19471 xmlFree(ntItem->keys);
19472 xmlFree(ntItem);
19473 }
19474 return (-1);
19475 }
19476
19477 goto selector_leave;
19478selector_key_error:
19479 /*
19480 * 4.2.1 (KEY) The ·target node set· and the
19481 * ·qualified node set· are equal, that is, every
19482 * member of the ·target node set· is also a member
19483 * of the ·qualified node set· and vice versa.
19484 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019485 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19486 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019487selector_leave:
19488 /*
19489 * Free the key-sequence if not added to the IDC table.
19490 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019491 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019492 xmlFree(*keySeq);
19493 *keySeq = NULL;
19494 }
19495 } /* if selector */
19496
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019497 sto->nbHistory--;
19498
19499deregister_check:
19500 /*
19501 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019502 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019503 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019504#if DEBUG_IDC
19505 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19506 sto->sel->xpath);
19507#endif
19508 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019509 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019510 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019511 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019512 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019513 nextsto = sto->next;
19514 /*
19515 * Unlink from the list of active XPath state objects.
19516 */
19517 vctxt->xpathStates = sto->next;
19518 sto->next = vctxt->xpathStatePool;
19519 /*
19520 * Link it to the pool of reusable state objects.
19521 */
19522 vctxt->xpathStatePool = sto;
19523 sto = nextsto;
19524 } else
19525 sto = sto->next;
19526 } /* while (sto != NULL) */
19527 return (0);
19528}
19529
19530/**
19531 * xmlSchemaIDCRegisterMatchers:
19532 * @vctxt: the WXS validation context
19533 * @elemDecl: the element declaration
19534 *
19535 * Creates helper objects to evaluate IDC selectors/fields
19536 * successively.
19537 *
19538 * Returns 0 if OK and -1 on internal errors.
19539 */
19540static int
19541xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19542 xmlSchemaElementPtr elemDecl)
19543{
19544 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19545 xmlSchemaIDCPtr idc, refIdc;
19546 xmlSchemaIDCAugPtr aidc;
19547
19548 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19549 if (idc == NULL)
19550 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019551
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019552#if DEBUG_IDC
19553 {
19554 xmlChar *str = NULL;
19555 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019556 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019557 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19558 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019559 FREE_AND_NULL(str)
19560 }
19561#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019562 if (vctxt->inode->idcMatchers != NULL) {
19563 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19564 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019565 return (-1);
19566 }
19567 do {
19568 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19569 /*
19570 * Since IDCs bubbles are expensive we need to know the
19571 * depth at which the bubbles should stop; this will be
19572 * the depth of the top-most keyref IDC. If no keyref
19573 * references a key/unique IDC, the bubbleDepth will
19574 * be -1, indicating that no bubbles are needed.
19575 */
19576 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19577 if (refIdc != NULL) {
19578 /*
19579 * Lookup the augmented IDC.
19580 */
19581 aidc = vctxt->aidcs;
19582 while (aidc != NULL) {
19583 if (aidc->def == refIdc)
19584 break;
19585 aidc = aidc->next;
19586 }
19587 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019588 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019589 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019590 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019591 return (-1);
19592 }
19593 if ((aidc->bubbleDepth == -1) ||
19594 (vctxt->depth < aidc->bubbleDepth))
19595 aidc->bubbleDepth = vctxt->depth;
19596 }
19597 }
19598 /*
19599 * Lookup the augmented IDC item for the IDC definition.
19600 */
19601 aidc = vctxt->aidcs;
19602 while (aidc != NULL) {
19603 if (aidc->def == idc)
19604 break;
19605 aidc = aidc->next;
19606 }
19607 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019608 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19609 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019610 return (-1);
19611 }
19612 /*
19613 * Create an IDC matcher for every IDC definition.
19614 */
19615 matcher = (xmlSchemaIDCMatcherPtr)
19616 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19617 if (matcher == NULL) {
19618 xmlSchemaVErrMemory(vctxt,
19619 "allocating an IDC matcher", NULL);
19620 return (-1);
19621 }
19622 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19623 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019624 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019625 else
19626 last->next = matcher;
19627 last = matcher;
19628
19629 matcher->type = IDC_MATCHER;
19630 matcher->depth = vctxt->depth;
19631 matcher->aidc = aidc;
19632#if DEBUG_IDC
19633 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19634#endif
19635 /*
19636 * Init the automaton state object.
19637 */
19638 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019639 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019640 return (-1);
19641
19642 idc = idc->next;
19643 } while (idc != NULL);
19644 return (0);
19645}
19646
19647/**
19648 * xmlSchemaBubbleIDCNodeTables:
19649 * @depth: the current tree depth
19650 *
19651 * Merges IDC bindings of an element at @depth into the corresponding IDC
19652 * bindings of its parent element. If a duplicate note-table entry is found,
19653 * both, the parent node-table entry and child entry are discarded from the
19654 * node-table of the parent.
19655 *
19656 * Returns 0 if OK and -1 on internal errors.
19657 */
19658static int
19659xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19660{
19661 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019662 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19663 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019664 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19665 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019666 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019667 int duplTop;
19668
19669 /*
19670 * The node table has the following sections:
19671 *
19672 * O --> old node-table entries (first)
19673 * O
19674 * + --> new node-table entries
19675 * +
19676 * % --> new duplicate node-table entries
19677 * %
19678 * # --> old duplicate node-table entries
19679 * # (last)
19680 *
19681 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019682 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019683 if (bind == NULL) {
19684 /* Fine, no table, no bubbles. */
19685 return (0);
19686 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019687
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019688 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19689 /*
19690 * Walk all bindings; create new or add to existing bindings.
19691 * Remove duplicate key-sequences.
19692 */
19693start_binding:
19694 while (bind != NULL) {
19695 /*
19696 * Skip keyref IDCs.
19697 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019698 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19699 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019700 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019701 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019702 /*
19703 * Check if the key/unique IDC table needs to be bubbled.
19704 */
19705 aidc = vctxt->aidcs;
19706 do {
19707 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019708 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019709 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019710 bind = bind->next;
19711 goto start_binding;
19712 }
19713 break;
19714 }
19715 aidc = aidc->next;
19716 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019717
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019718 if (parTable != NULL)
19719 parBind = *parTable;
19720 while (parBind != NULL) {
19721 /*
19722 * Search a matching parent binding for the
19723 * IDC definition.
19724 */
19725 if (parBind->definition == bind->definition) {
19726
19727 /*
19728 * Compare every node-table entry of the child node,
19729 * i.e. the key-sequence within, ...
19730 */
19731 oldNum = parBind->nbNodes; /* Skip newly added items. */
19732 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019733 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019734
19735 for (i = 0; i < bind->nbNodes; i++) {
19736 node = bind->nodeTable[i];
19737 if (node == NULL)
19738 continue;
19739 /*
19740 * ...with every key-sequence of the parent node, already
19741 * evaluated to be a duplicate key-sequence.
19742 */
19743 if (parBind->nbDupls != 0) {
19744 j = bind->nbNodes + newDupls;
19745 while (j < duplTop) {
19746 parNode = parBind->nodeTable[j];
19747 for (k = 0; k < bind->definition->nbFields; k++) {
19748 key = node->keys[k];
19749 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019750 ret = xmlSchemaAreValuesEqual(key->val,
19751 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019752 if (ret == -1) {
19753 /* TODO: Internal error */
19754 return(-1);
19755 } else if (ret == 0)
19756 break;
19757
19758 }
19759 if (ret == 1)
19760 /* Duplicate found. */
19761 break;
19762 j++;
19763 }
19764 if (j != duplTop) {
19765 /* Duplicate found. */
19766 continue;
19767 }
19768 }
19769 /*
19770 * ... and with every key-sequence of the parent node.
19771 */
19772 j = 0;
19773 while (j < oldNum) {
19774 parNode = parBind->nodeTable[j];
19775 /*
19776 * Compare key by key.
19777 */
19778 for (k = 0; k < parBind->definition->nbFields; k++) {
19779 key = node->keys[k];
19780 parKey = parNode->keys[k];
19781
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019782 ret = xmlSchemaAreValuesEqual(key->val,
19783 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019784 if (ret == -1) {
19785 /* TODO: Internal error */
19786 } else if (ret == 0)
19787 break;
19788
19789 }
19790 if (ret == 1)
19791 /*
19792 * The key-sequences are equal.
19793 */
19794 break;
19795 j++;
19796 }
19797 if (j != oldNum) {
19798 /*
19799 * Handle duplicates.
19800 */
19801 newDupls++;
19802 oldNum--;
19803 parBind->nbNodes--;
19804 /*
19805 * Move last old item to pos of duplicate.
19806 */
19807 parBind->nodeTable[j] =
19808 parBind->nodeTable[oldNum];
19809
19810 if (parBind->nbNodes != oldNum) {
19811 /*
19812 * If new items exist, move last new item to
19813 * last of old items.
19814 */
19815 parBind->nodeTable[oldNum] =
19816 parBind->nodeTable[parBind->nbNodes];
19817 }
19818 /*
19819 * Move duplicate to last pos of new/old items.
19820 */
19821 parBind->nodeTable[parBind->nbNodes] = parNode;
19822
19823 } else {
19824 /*
19825 * Add the node-table entry (node and key-sequence) of
19826 * the child node to the node table of the parent node.
19827 */
19828 if (parBind->nodeTable == NULL) {
19829 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019830 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019831 if (parBind->nodeTable == NULL) {
19832 xmlSchemaVErrMemory(NULL,
19833 "allocating IDC list of node-table items", NULL);
19834 return(-1);
19835 }
19836 parBind->sizeNodes = 1;
19837 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019838 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019839 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19840 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19841 sizeof(xmlSchemaPSVIIDCNodePtr));
19842 if (parBind->nodeTable == NULL) {
19843 xmlSchemaVErrMemory(NULL,
19844 "re-allocating IDC list of node-table items", NULL);
19845 return(-1);
19846 }
19847 }
19848
19849 /*
19850 * Move first old duplicate to last position
19851 * of old duplicates +1.
19852 */
19853 if (parBind->nbDupls != 0) {
19854 parBind->nodeTable[duplTop] =
19855 parBind->nodeTable[parBind->nbNodes + newDupls];
19856 }
19857 /*
19858 * Move first new duplicate to last position of
19859 * new duplicates +1.
19860 */
19861 if (newDupls != 0) {
19862 parBind->nodeTable[parBind->nbNodes + newDupls] =
19863 parBind->nodeTable[parBind->nbNodes];
19864 }
19865 /*
19866 * Append the new node-table entry to the 'new node-table
19867 * entries' section.
19868 */
19869 parBind->nodeTable[parBind->nbNodes] = node;
19870 parBind->nbNodes++;
19871 duplTop++;
19872 }
19873 }
19874 parBind->nbDupls += newDupls;
19875 break;
19876 }
19877 if (parBind->next == NULL)
19878 lastParBind = parBind;
19879 parBind = parBind->next;
19880 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019881 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019882 /*
19883 * No binding for the IDC was found: create a new one and
19884 * copy all node-tables.
19885 */
19886 parBind = xmlSchemaIDCNewBinding(bind->definition);
19887 if (parBind == NULL)
19888 return(-1);
19889
19890 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19891 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19892 if (parBind->nodeTable == NULL) {
19893 xmlSchemaVErrMemory(NULL,
19894 "allocating an array of IDC node-table items", NULL);
19895 xmlSchemaIDCFreeBinding(parBind);
19896 return(-1);
19897 }
19898 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019899 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019900 memcpy(parBind->nodeTable, bind->nodeTable,
19901 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019902 if (*parTable == NULL)
19903 *parTable = parBind;
19904 else
19905 lastParBind->next = parBind;
19906 }
19907 bind = bind->next;
19908 }
19909 return (0);
19910}
19911
19912/**
19913 * xmlSchemaCheckCVCIDCKeyRef:
19914 * @vctxt: the WXS validation context
19915 * @elemDecl: the element declaration
19916 *
19917 * Check the cvc-idc-keyref constraints.
19918 */
19919static int
19920xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19921{
19922 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19923
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019924 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019925 /*
19926 * Find a keyref.
19927 */
19928 while (refbind != NULL) {
19929 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19930 int i, j, k, res;
19931 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19932 xmlSchemaPSVIIDCKeyPtr refKey, key;
19933
19934 /*
19935 * Find the referred key/unique.
19936 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019937 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019938 do {
19939 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19940 bind->definition)
19941 break;
19942 bind = bind->next;
19943 } while (bind != NULL);
19944
19945 /*
19946 * Search for a matching key-sequences.
19947 */
19948 for (i = 0; i < refbind->nbNodes; i++) {
19949 res = 0;
19950 if (bind != NULL) {
19951 refKeys = refbind->nodeTable[i]->keys;
19952 for (j = 0; j < bind->nbNodes; j++) {
19953 keys = bind->nodeTable[j]->keys;
19954 for (k = 0; k < bind->definition->nbFields; k++) {
19955 refKey = refKeys[k];
19956 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019957 res = xmlSchemaAreValuesEqual(key->val,
19958 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019959 if (res == 0)
19960 break;
19961 else if (res == -1) {
19962 return (-1);
19963 }
19964 }
19965 if (res == 1) {
19966 /*
19967 * Match found.
19968 */
19969 break;
19970 }
19971 }
19972 }
19973 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019974 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019975 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019976 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19977 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019978 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019979 "No match found for key-sequence %s of key "
19980 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019981 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019982 refbind->nodeTable[i]->keys,
19983 refbind->definition->nbFields),
19984 xmlSchemaFormatQName(&strB,
19985 refbind->definition->targetNamespace,
19986 refbind->definition->name));
19987 FREE_AND_NULL(str);
19988 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019989 }
19990 }
19991 }
19992 refbind = refbind->next;
19993 }
19994 return (0);
19995}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019996
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019997/************************************************************************
19998 * *
19999 * XML Reader validation code *
20000 * *
20001 ************************************************************************/
20002
20003static xmlSchemaAttrInfoPtr
20004xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020005{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020006 xmlSchemaAttrInfoPtr iattr;
20007 /*
20008 * Grow/create list of attribute infos.
20009 */
20010 if (vctxt->attrInfos == NULL) {
20011 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20012 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
20013 vctxt->sizeAttrInfos = 1;
20014 if (vctxt->attrInfos == NULL) {
20015 xmlSchemaVErrMemory(vctxt,
20016 "allocating attribute info list", NULL);
20017 return (NULL);
20018 }
20019 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
20020 vctxt->sizeAttrInfos++;
20021 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20022 xmlRealloc(vctxt->attrInfos,
20023 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
20024 if (vctxt->attrInfos == NULL) {
20025 xmlSchemaVErrMemory(vctxt,
20026 "re-allocating attribute info list", NULL);
20027 return (NULL);
20028 }
20029 } else {
20030 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
20031 if (iattr->localName != NULL) {
20032 VERROR_INT("xmlSchemaGetFreshAttrInfo",
20033 "attr info not cleared");
20034 return (NULL);
20035 }
20036 iattr->nodeType = XML_ATTRIBUTE_NODE;
20037 return (iattr);
20038 }
20039 /*
20040 * Create an attribute info.
20041 */
20042 iattr = (xmlSchemaAttrInfoPtr)
20043 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20044 if (iattr == NULL) {
20045 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20046 return (NULL);
20047 }
20048 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20049 iattr->nodeType = XML_ATTRIBUTE_NODE;
20050 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20051
20052 return (iattr);
20053}
20054
20055static int
20056xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20057 xmlNodePtr attrNode,
20058 const xmlChar *localName,
20059 const xmlChar *nsName,
20060 int ownedNames,
20061 xmlChar *value,
20062 int ownedValue)
20063{
20064 xmlSchemaAttrInfoPtr attr;
20065
20066 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20067 if (attr == NULL) {
20068 VERROR_INT("xmlSchemaPushAttribute",
20069 "calling xmlSchemaGetFreshAttrInfo()");
20070 return (-1);
20071 }
20072 attr->node = attrNode;
20073 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20074 attr->localName = localName;
20075 attr->nsName = nsName;
20076 if (ownedNames)
20077 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20078 /*
20079 * Evaluate if it's an XSI attribute.
20080 */
20081 if (nsName != NULL) {
20082 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20083 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20084 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20085 }
20086 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20087 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20088 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20089 }
20090 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20091 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20092 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20093 }
20094 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20095 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20096 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20097 }
20098 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20099 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20100 }
20101 }
20102 attr->value = value;
20103 if (ownedValue)
20104 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20105 if (attr->metaType != 0)
20106 attr->state = XML_SCHEMAS_ATTR_META;
20107 return (0);
20108}
20109
20110static void
20111xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20112{
20113 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20114 FREE_AND_NULL(ielem->localName);
20115 FREE_AND_NULL(ielem->nsName);
20116 } else {
20117 ielem->localName = NULL;
20118 ielem->nsName = NULL;
20119 }
20120 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20121 FREE_AND_NULL(ielem->value);
20122 } else {
20123 ielem->value = NULL;
20124 }
20125 if (ielem->val != NULL) {
20126 xmlSchemaFreeValue(ielem->val);
20127 ielem->val = NULL;
20128 }
20129 if (ielem->idcMatchers != NULL) {
20130 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20131 ielem->idcMatchers = NULL;
20132 }
20133 if (ielem->idcTable != NULL) {
20134 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20135 ielem->idcTable = NULL;
20136 }
20137 if (ielem->regexCtxt != NULL) {
20138 xmlRegFreeExecCtxt(ielem->regexCtxt);
20139 ielem->regexCtxt = NULL;
20140 }
20141 if (ielem->nsBindings != NULL) {
20142 xmlFree((xmlChar **)ielem->nsBindings);
20143 ielem->nsBindings = NULL;
20144 ielem->nbNsBindings = 0;
20145 ielem->sizeNsBindings = 0;
20146 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020147}
20148
20149/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020150 * xmlSchemaGetFreshElemInfo:
20151 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020152 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020153 * Creates/reuses and initializes the element info item for
20154 * the currect tree depth.
20155 *
20156 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020157 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020158static xmlSchemaNodeInfoPtr
20159xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020160{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020161 xmlSchemaNodeInfoPtr info = NULL;
20162
20163 if (vctxt->depth > vctxt->sizeElemInfos) {
20164 VERROR_INT("xmlSchemaGetFreshElemInfo",
20165 "inconsistent depth encountered");
20166 return (NULL);
20167 }
20168 if (vctxt->elemInfos == NULL) {
20169 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20170 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20171 if (vctxt->elemInfos == NULL) {
20172 xmlSchemaVErrMemory(vctxt,
20173 "allocating the element info array", NULL);
20174 return (NULL);
20175 }
20176 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20177 vctxt->sizeElemInfos = 10;
20178 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20179 int i = vctxt->sizeElemInfos;
20180
20181 vctxt->sizeElemInfos *= 2;
20182 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20183 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20184 sizeof(xmlSchemaNodeInfoPtr));
20185 if (vctxt->elemInfos == NULL) {
20186 xmlSchemaVErrMemory(vctxt,
20187 "re-allocating the element info array", NULL);
20188 return (NULL);
20189 }
20190 /*
20191 * We need the new memory to be NULLed.
20192 * TODO: Use memset instead?
20193 */
20194 for (; i < vctxt->sizeElemInfos; i++)
20195 vctxt->elemInfos[i] = NULL;
20196 } else
20197 info = vctxt->elemInfos[vctxt->depth];
20198
20199 if (info == NULL) {
20200 info = (xmlSchemaNodeInfoPtr)
20201 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20202 if (info == NULL) {
20203 xmlSchemaVErrMemory(vctxt,
20204 "allocating an element info", NULL);
20205 return (NULL);
20206 }
20207 vctxt->elemInfos[vctxt->depth] = info;
20208 } else {
20209 if (info->localName != NULL) {
20210 VERROR_INT("xmlSchemaGetFreshElemInfo",
20211 "elem info has not been cleared");
20212 return (NULL);
20213 }
20214 }
20215 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20216 info->nodeType = XML_ELEMENT_NODE;
20217 info->depth = vctxt->depth;
20218
20219 return (info);
20220}
20221
20222#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20223#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20224#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20225
20226static int
20227xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20228 xmlNodePtr node,
20229 xmlSchemaTypePtr type,
20230 xmlSchemaValType valType,
20231 const xmlChar * value,
20232 xmlSchemaValPtr val,
20233 unsigned long length,
20234 int fireErrors)
20235{
20236 int ret, error = 0;
20237
20238 xmlSchemaTypePtr tmpType;
20239 xmlSchemaFacetLinkPtr facetLink;
20240 xmlSchemaFacetPtr facet;
20241 unsigned long len = 0;
20242 xmlSchemaWhitespaceValueType ws;
20243
20244 /*
20245 * In Libxml2, derived built-in types have currently no explicit facets.
20246 */
20247 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020248 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020249
20250 /*
20251 * NOTE: Do not jump away, if the facetSet of the given type is
20252 * empty: until now, "pattern" and "enumeration" facets of the
20253 * *base types* need to be checked as well.
20254 */
20255 if (type->facetSet == NULL)
20256 goto pattern_and_enum;
20257
20258 if (! VARIETY_ATOMIC(type)) {
20259 if (VARIETY_LIST(type))
20260 goto variety_list;
20261 else
20262 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020263 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020264 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020265 * Whitespace handling is only of importance for string-based
20266 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020267 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020268 tmpType = xmlSchemaGetPrimitiveType(type);
20269 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20270 IS_ANY_SIMPLE_TYPE(tmpType)) {
20271 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20272 } else
20273 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20274 /*
20275 * If the value was not computed (for string or
20276 * anySimpleType based types), then use the provided
20277 * type.
20278 */
20279 if (val == NULL)
20280 valType = valType;
20281 else
20282 valType = xmlSchemaGetValType(val);
20283
20284 ret = 0;
20285 for (facetLink = type->facetSet; facetLink != NULL;
20286 facetLink = facetLink->next) {
20287 /*
20288 * Skip the pattern "whiteSpace": it is used to
20289 * format the character content beforehand.
20290 */
20291 switch (facetLink->facet->type) {
20292 case XML_SCHEMA_FACET_WHITESPACE:
20293 case XML_SCHEMA_FACET_PATTERN:
20294 case XML_SCHEMA_FACET_ENUMERATION:
20295 continue;
20296 case XML_SCHEMA_FACET_LENGTH:
20297 case XML_SCHEMA_FACET_MINLENGTH:
20298 case XML_SCHEMA_FACET_MAXLENGTH:
20299 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20300 valType, value, val, &len, ws);
20301 break;
20302 default:
20303 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20304 valType, value, val, ws);
20305 break;
20306 }
20307 if (ret < 0) {
20308 AERROR_INT("xmlSchemaValidateFacets",
20309 "validating against a atomic type facet");
20310 return (-1);
20311 } else if (ret > 0) {
20312 if (fireErrors)
20313 xmlSchemaFacetErr(actxt, ret, node,
20314 value, len, type, facetLink->facet, NULL, NULL, NULL);
20315 else
20316 return (ret);
20317 if (error == 0)
20318 error = ret;
20319 }
20320 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020321 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020322
20323variety_list:
20324 if (! VARIETY_LIST(type))
20325 goto pattern_and_enum;
20326 /*
20327 * "length", "minLength" and "maxLength" of list types.
20328 */
20329 ret = 0;
20330 for (facetLink = type->facetSet; facetLink != NULL;
20331 facetLink = facetLink->next) {
20332
20333 switch (facetLink->facet->type) {
20334 case XML_SCHEMA_FACET_LENGTH:
20335 case XML_SCHEMA_FACET_MINLENGTH:
20336 case XML_SCHEMA_FACET_MAXLENGTH:
20337 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20338 value, length, NULL);
20339 break;
20340 default:
20341 continue;
20342 }
20343 if (ret < 0) {
20344 AERROR_INT("xmlSchemaValidateFacets",
20345 "validating against a list type facet");
20346 return (-1);
20347 } else if (ret > 0) {
20348 if (fireErrors)
20349 xmlSchemaFacetErr(actxt, ret, node,
20350 value, length, type, facetLink->facet, NULL, NULL, NULL);
20351 else
20352 return (ret);
20353 if (error == 0)
20354 error = ret;
20355 }
20356 ret = 0;
20357 }
20358
20359pattern_and_enum:
20360 if (error >= 0) {
20361 int found = 0;
20362 /*
20363 * Process enumerations. Facet values are in the value space
20364 * of the defining type's base type. This seems to be a bug in the
20365 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20366 * Only the first set of enumerations in the ancestor-or-self axis
20367 * is used for validation.
20368 */
20369 ret = 0;
20370 tmpType = type;
20371 do {
20372 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20373 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20374 continue;
20375 found = 1;
20376 ret = xmlSchemaAreValuesEqual(facet->val, val);
20377 if (ret == 1)
20378 break;
20379 else if (ret < 0) {
20380 AERROR_INT("xmlSchemaValidateFacets",
20381 "validating against an enumeration facet");
20382 return (-1);
20383 }
20384 }
20385 if (ret != 0)
20386 break;
20387 tmpType = tmpType->baseType;
20388 } while ((tmpType != NULL) &&
20389 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20390 if (found && (ret == 0)) {
20391 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20392 if (fireErrors) {
20393 xmlSchemaFacetErr(actxt, ret, node,
20394 value, 0, type, NULL, NULL, NULL, NULL);
20395 } else
20396 return (ret);
20397 if (error == 0)
20398 error = ret;
20399 }
20400 }
20401
20402 if (error >= 0) {
20403 int found;
20404 /*
20405 * Process patters. Pattern facets are ORed at type level
20406 * and ANDed if derived. Walk the base type axis.
20407 */
20408 tmpType = type;
20409 facet = NULL;
20410 do {
20411 found = 0;
20412 for (facetLink = tmpType->facetSet; facetLink != NULL;
20413 facetLink = facetLink->next) {
20414 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20415 continue;
20416 found = 1;
20417 /*
20418 * NOTE that for patterns, @value needs to be the
20419 * normalized vaule.
20420 */
20421 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20422 if (ret == 1)
20423 break;
20424 else if (ret < 0) {
20425 AERROR_INT("xmlSchemaValidateFacets",
20426 "validating against a pattern facet");
20427 return (-1);
20428 } else {
20429 /*
20430 * Save the last non-validating facet.
20431 */
20432 facet = facetLink->facet;
20433 }
20434 }
20435 if (found && (ret != 1)) {
20436 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20437 if (fireErrors) {
20438 xmlSchemaFacetErr(actxt, ret, node,
20439 value, 0, type, facet, NULL, NULL, NULL);
20440 } else
20441 return (ret);
20442 if (error == 0)
20443 error = ret;
20444 break;
20445 }
20446 tmpType = tmpType->baseType;
20447 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20448 }
20449
20450 return (error);
20451}
20452
20453static xmlChar *
20454xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20455 const xmlChar *value)
20456{
20457 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20458 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20459 return (xmlSchemaCollapseString(value));
20460 case XML_SCHEMA_WHITESPACE_REPLACE:
20461 return (xmlSchemaWhiteSpaceReplace(value));
20462 default:
20463 return (NULL);
20464 }
20465}
20466
20467static int
20468xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20469 const xmlChar *value,
20470 xmlSchemaValPtr *val,
20471 int valNeeded)
20472{
20473 int ret;
20474 const xmlChar *nsName;
20475 xmlChar *local, *prefix = NULL;
20476
20477 ret = xmlValidateQName(value, 1);
20478 if (ret != 0) {
20479 if (ret == -1) {
20480 VERROR_INT("xmlSchemaValidateQName",
20481 "calling xmlValidateQName()");
20482 return (-1);
20483 }
20484 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20485 }
20486 /*
20487 * NOTE: xmlSplitQName2 will always return a duplicated
20488 * strings.
20489 */
20490 local = xmlSplitQName2(value, &prefix);
20491 if (local == NULL)
20492 local = xmlStrdup(value);
20493 /*
20494 * OPTIMIZE TODO: Use flags for:
20495 * - is there any namespace binding?
20496 * - is there a default namespace?
20497 */
20498 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20499
20500 if (prefix != NULL) {
20501 xmlFree(prefix);
20502 /*
20503 * A namespace must be found if the prefix is
20504 * NOT NULL.
20505 */
20506 if (nsName == NULL) {
20507 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20508 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20509 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20510 "The QName value '%s' has no "
20511 "corresponding namespace declaration in "
20512 "scope", value, NULL);
20513 if (local != NULL)
20514 xmlFree(local);
20515 return (ret);
20516 }
20517 }
20518 if (valNeeded && val) {
20519 if (nsName != NULL)
20520 *val = xmlSchemaNewQNameValue(
20521 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20522 else
20523 *val = xmlSchemaNewQNameValue(NULL,
20524 BAD_CAST local);
20525 } else
20526 xmlFree(local);
20527 return (0);
20528}
20529
20530/*
20531* cvc-simple-type
20532*/
20533static int
20534xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20535 xmlNodePtr node,
20536 xmlSchemaTypePtr type,
20537 const xmlChar *value,
20538 xmlSchemaValPtr *retVal,
20539 int fireErrors,
20540 int normalize,
20541 int isNormalized)
20542{
20543 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20544 xmlSchemaValPtr val = NULL;
20545 xmlSchemaWhitespaceValueType ws;
20546 xmlChar *normValue = NULL;
20547
20548#define NORMALIZE(atype) \
20549 if ((! isNormalized) && \
20550 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20551 normValue = xmlSchemaNormalizeValue(atype, value); \
20552 if (normValue != NULL) \
20553 value = normValue; \
20554 isNormalized = 1; \
20555 }
20556
20557 if ((retVal != NULL) && (*retVal != NULL)) {
20558 xmlSchemaFreeValue(*retVal);
20559 *retVal = NULL;
20560 }
20561 /*
20562 * 3.14.4 Simple Type Definition Validation Rules
20563 * Validation Rule: String Valid
20564 */
20565 /*
20566 * 1 It is schema-valid with respect to that definition as defined
20567 * by Datatype Valid in [XML Schemas: Datatypes].
20568 */
20569 /*
20570 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20571 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20572 * the string must be a ·declared entity name·.
20573 */
20574 /*
20575 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20576 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20577 * then every whitespace-delimited substring of the string must be a ·declared
20578 * entity name·.
20579 */
20580 /*
20581 * 2.3 otherwise no further condition applies.
20582 */
20583 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20584 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020585 if (value == NULL)
20586 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020587 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20588 xmlSchemaTypePtr biType; /* The built-in type. */
20589 /*
20590 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20591 * a literal in the ·lexical space· of {base type definition}"
20592 */
20593 /*
20594 * Whitespace-normalize.
20595 */
20596 NORMALIZE(type);
20597 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20598 /*
20599 * Get the built-in type.
20600 */
20601 biType = type->baseType;
20602 while ((biType != NULL) &&
20603 (biType->type != XML_SCHEMA_TYPE_BASIC))
20604 biType = biType->baseType;
20605
20606 if (biType == NULL) {
20607 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20608 "could not get the built-in type");
20609 goto internal_error;
20610 }
20611 } else
20612 biType = type;
20613 /*
20614 * NOTATIONs need to be processed here, since they need
20615 * to lookup in the hashtable of NOTATION declarations of the schema.
20616 */
20617 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20618 switch (biType->builtInType) {
20619 case XML_SCHEMAS_NOTATION:
20620 ret = xmlSchemaValidateNotation(
20621 (xmlSchemaValidCtxtPtr) actxt,
20622 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20623 NULL, value, &val, valNeeded);
20624 break;
20625 case XML_SCHEMAS_QNAME:
20626 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20627 value, &val, valNeeded);
20628 break;
20629 default:
20630 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20631 if (valNeeded)
20632 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20633 value, &val, NULL);
20634 else
20635 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20636 value, NULL, NULL);
20637 break;
20638 }
20639 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20640 switch (biType->builtInType) {
20641 case XML_SCHEMAS_NOTATION:
20642 ret = xmlSchemaValidateNotation(NULL,
20643 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20644 value, &val, valNeeded);
20645 break;
20646 default:
20647 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20648 if (valNeeded)
20649 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20650 value, &val, node);
20651 else
20652 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20653 value, NULL, node);
20654 break;
20655 }
20656 } else {
20657 /*
20658 * Validation via a public API is not implemented yet.
20659 */
20660 TODO
20661 goto internal_error;
20662 }
20663 if (ret != 0) {
20664 if (ret < 0) {
20665 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20666 "validating against a built-in type");
20667 goto internal_error;
20668 }
20669 if (VARIETY_LIST(type))
20670 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20671 else
20672 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20673 }
20674 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20675 /*
20676 * Check facets.
20677 */
20678 ret = xmlSchemaValidateFacets(actxt, node, type,
20679 (xmlSchemaValType) biType->builtInType, value, val,
20680 0, fireErrors);
20681 if (ret != 0) {
20682 if (ret < 0) {
20683 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20684 "validating facets of atomic simple type");
20685 goto internal_error;
20686 }
20687 if (VARIETY_LIST(type))
20688 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20689 else
20690 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20691 }
20692 }
20693 if (fireErrors && (ret > 0))
20694 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20695 } else if (VARIETY_LIST(type)) {
20696
20697 xmlSchemaTypePtr itemType;
20698 const xmlChar *cur, *end;
20699 xmlChar *tmpValue = NULL;
20700 unsigned long len = 0;
20701 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20702 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20703 * of white space separated tokens, each of which ·match·es a literal
20704 * in the ·lexical space· of {item type definition}
20705 */
20706 /*
20707 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20708 * the list type has an enum or pattern facet.
20709 */
20710 NORMALIZE(type);
20711 /*
20712 * VAL TODO: Optimize validation of empty values.
20713 * VAL TODO: We do not have computed values for lists.
20714 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020715 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020716 cur = value;
20717 do {
20718 while (IS_BLANK_CH(*cur))
20719 cur++;
20720 end = cur;
20721 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20722 end++;
20723 if (end == cur)
20724 break;
20725 tmpValue = xmlStrndup(cur, end - cur);
20726 len++;
20727
20728 if (valNeeded)
20729 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20730 tmpValue, &curVal, fireErrors, 0, 1);
20731 else
20732 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20733 tmpValue, NULL, fireErrors, 0, 1);
20734 FREE_AND_NULL(tmpValue);
20735 if (curVal != NULL) {
20736 /*
20737 * Add to list of computed values.
20738 */
20739 if (val == NULL)
20740 val = curVal;
20741 else
20742 xmlSchemaValueAppend(prevVal, curVal);
20743 prevVal = curVal;
20744 curVal = NULL;
20745 }
20746 if (ret != 0) {
20747 if (ret < 0) {
20748 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20749 "validating an item of list simple type");
20750 goto internal_error;
20751 }
20752 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20753 break;
20754 }
20755 cur = end;
20756 } while (*cur != 0);
20757 FREE_AND_NULL(tmpValue);
20758 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20759 /*
20760 * Apply facets (pattern, enumeration).
20761 */
20762 ret = xmlSchemaValidateFacets(actxt, node, type,
20763 XML_SCHEMAS_UNKNOWN, value, val,
20764 len, fireErrors);
20765 if (ret != 0) {
20766 if (ret < 0) {
20767 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20768 "validating facets of list simple type");
20769 goto internal_error;
20770 }
20771 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20772 }
20773 }
20774 if (fireErrors && (ret > 0)) {
20775 /*
20776 * Report the normalized value.
20777 */
20778 normalize = 1;
20779 NORMALIZE(type);
20780 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20781 }
20782 } else if (VARIETY_UNION(type)) {
20783 xmlSchemaTypeLinkPtr memberLink;
20784 /*
20785 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20786 * not apply directly; however, the normalization behavior of ·union·
20787 * types is controlled by the value of whiteSpace on that one of the
20788 * ·memberTypes· against which the ·union· is successfully validated.
20789 *
20790 * This means that the value is normalized by the first validating
20791 * member type, then the facets of the union type are applied. This
20792 * needs changing of the value!
20793 */
20794
20795 /*
20796 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20797 * literal in the ·lexical space· of at least one member of
20798 * {member type definitions}
20799 */
20800 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20801 if (memberLink == NULL) {
20802 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20803 "union simple type has no member types");
20804 goto internal_error;
20805 }
20806 /*
20807 * Always normalize union type values, since we currently
20808 * cannot store the whitespace information with the value
20809 * itself; otherwise a later value-comparison would be
20810 * not possible.
20811 */
20812 while (memberLink != NULL) {
20813 if (valNeeded)
20814 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20815 memberLink->type, value, &val, 0, 1, 0);
20816 else
20817 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20818 memberLink->type, value, NULL, 0, 1, 0);
20819 if (ret <= 0)
20820 break;
20821 memberLink = memberLink->next;
20822 }
20823 if (ret != 0) {
20824 if (ret < 0) {
20825 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20826 "validating members of union simple type");
20827 goto internal_error;
20828 }
20829 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20830 }
20831 /*
20832 * Apply facets (pattern, enumeration).
20833 */
20834 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20835 /*
20836 * The normalization behavior of ·union· types is controlled by
20837 * the value of whiteSpace on that one of the ·memberTypes·
20838 * against which the ·union· is successfully validated.
20839 */
20840 NORMALIZE(memberLink->type);
20841 ret = xmlSchemaValidateFacets(actxt, node, type,
20842 XML_SCHEMAS_UNKNOWN, value, val,
20843 0, fireErrors);
20844 if (ret != 0) {
20845 if (ret < 0) {
20846 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20847 "validating facets of union simple type");
20848 goto internal_error;
20849 }
20850 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20851 }
20852 }
20853 if (fireErrors && (ret > 0))
20854 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20855 }
20856
20857 if (normValue != NULL)
20858 xmlFree(normValue);
20859 if (ret == 0) {
20860 if (retVal != NULL)
20861 *retVal = val;
20862 else if (val != NULL)
20863 xmlSchemaFreeValue(val);
20864 } else if (val != NULL)
20865 xmlSchemaFreeValue(val);
20866 return (ret);
20867internal_error:
20868 if (normValue != NULL)
20869 xmlFree(normValue);
20870 if (val != NULL)
20871 xmlSchemaFreeValue(val);
20872 return (-1);
20873}
20874
20875static int
20876xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20877 const xmlChar *value,
20878 const xmlChar **nsName,
20879 const xmlChar **localName)
20880{
20881 int ret = 0;
20882
20883 if ((nsName == NULL) || (localName == NULL))
20884 return (-1);
20885 *nsName = NULL;
20886 *localName = NULL;
20887
20888 ret = xmlValidateQName(value, 1);
20889 if (ret == -1)
20890 return (-1);
20891 if (ret > 0) {
20892 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20893 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20894 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20895 return (1);
20896 }
20897 {
20898 xmlChar *local = NULL;
20899 xmlChar *prefix;
20900
20901 /*
20902 * NOTE: xmlSplitQName2 will return a duplicated
20903 * string.
20904 */
20905 local = xmlSplitQName2(value, &prefix);
20906 VAL_CREATE_DICT;
20907 if (local == NULL)
20908 *localName = xmlDictLookup(vctxt->dict, value, -1);
20909 else {
20910 *localName = xmlDictLookup(vctxt->dict, local, -1);
20911 xmlFree(local);
20912 }
20913
20914 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20915
20916 if (prefix != NULL) {
20917 xmlFree(prefix);
20918 /*
20919 * A namespace must be found if the prefix is NOT NULL.
20920 */
20921 if (*nsName == NULL) {
20922 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20923 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20924 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20925 "The QName value '%s' has no "
20926 "corresponding namespace declaration in scope",
20927 value, NULL);
20928 return (2);
20929 }
20930 }
20931 }
20932 return (0);
20933}
20934
20935static int
20936xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20937 xmlSchemaAttrInfoPtr iattr,
20938 xmlSchemaTypePtr *localType,
20939 xmlSchemaElementPtr elemDecl)
20940{
20941 int ret = 0;
20942 /*
20943 * cvc-elt (3.3.4) : (4)
20944 * AND
20945 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20946 * (1.2.1.2.1) - (1.2.1.2.4)
20947 * Handle 'xsi:type'.
20948 */
20949 if (localType == NULL)
20950 return (-1);
20951 *localType = NULL;
20952 if (iattr == NULL)
20953 return (0);
20954 else {
20955 const xmlChar *nsName = NULL, *local = NULL;
20956 /*
20957 * TODO: We should report a *warning* that the type was overriden
20958 * by the instance.
20959 */
20960 ACTIVATE_ATTRIBUTE(iattr);
20961 /*
20962 * (cvc-elt) (3.3.4) : (4.1)
20963 * (cvc-assess-elt) (1.2.1.2.2)
20964 */
20965 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20966 &nsName, &local);
20967 if (ret != 0) {
20968 if (ret < 0) {
20969 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20970 "calling xmlSchemaQNameExpand() to validate the "
20971 "attribute 'xsi:type'");
20972 goto internal_error;
20973 }
20974 goto exit;
20975 }
20976 /*
20977 * (cvc-elt) (3.3.4) : (4.2)
20978 * (cvc-assess-elt) (1.2.1.2.3)
20979 */
20980 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20981 if (*localType == NULL) {
20982 xmlChar *str = NULL;
20983
20984 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20985 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20986 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20987 "The QName value '%s' of the xsi:type attribute does not "
20988 "resolve to a type definition",
20989 xmlSchemaFormatQName(&str, nsName, local), NULL);
20990 FREE_AND_NULL(str);
20991 ret = vctxt->err;
20992 goto exit;
20993 }
20994 if (elemDecl != NULL) {
20995 int set = 0;
20996
20997 /*
20998 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20999 * "The ·local type definition· must be validly
21000 * derived from the {type definition} given the union of
21001 * the {disallowed substitutions} and the {type definition}'s
21002 * {prohibited substitutions}, as defined in
21003 * Type Derivation OK (Complex) (§3.4.6)
21004 * (if it is a complex type definition),
21005 * or given {disallowed substitutions} as defined in Type
21006 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21007 * definition)."
21008 *
21009 * {disallowed substitutions}: the "block" on the element decl.
21010 * {prohibited substitutions}: the "block" on the type def.
21011 */
21012 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21013 (elemDecl->subtypes->flags &
21014 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21015 set |= SUBSET_EXTENSION;
21016
21017 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21018 (elemDecl->subtypes->flags &
21019 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21020 set |= SUBSET_RESTRICTION;
21021
21022 if (xmlSchemaCheckCOSDerivedOK(*localType,
21023 elemDecl->subtypes, set) != 0) {
21024 xmlChar *str = NULL;
21025
21026 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21027 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
21028 "The type definition '%s', specified by xsi:type, is "
21029 "blocked or not validly derived from the type definition "
21030 "of the element declaration",
21031 xmlSchemaFormatQName(&str,
21032 (*localType)->targetNamespace,
21033 (*localType)->name),
21034 NULL);
21035 FREE_AND_NULL(str);
21036 ret = vctxt->err;
21037 *localType = NULL;
21038 }
21039 }
21040 }
21041exit:
21042 ACTIVATE_ELEM;
21043 return (ret);
21044internal_error:
21045 ACTIVATE_ELEM;
21046 return (-1);
21047}
21048
21049static int
21050xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21051{
21052 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21053 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21054
21055 /*
21056 * cvc-elt (3.3.4) : 1
21057 */
21058 if (elemDecl == NULL) {
21059 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21060 "No matching declaration available");
21061 return (vctxt->err);
21062 }
21063 /*
21064 * cvc-elt (3.3.4) : 2
21065 */
21066 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21067 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21068 "The element declaration is abstract");
21069 return (vctxt->err);
21070 }
21071 if (actualType == NULL) {
21072 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21073 "The type definition is absent");
21074 return (XML_SCHEMAV_CVC_TYPE_1);
21075 }
21076 if (vctxt->nbAttrInfos != 0) {
21077 int ret;
21078 xmlSchemaAttrInfoPtr iattr;
21079 /*
21080 * cvc-elt (3.3.4) : 3
21081 * Handle 'xsi:nil'.
21082 */
21083 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21084 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21085 if (iattr) {
21086 ACTIVATE_ATTRIBUTE(iattr);
21087 /*
21088 * Validate the value.
21089 */
21090 ret = xmlSchemaVCheckCVCSimpleType(
21091 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21092 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21093 iattr->value, &(iattr->val), 1, 0, 0);
21094 ACTIVATE_ELEM;
21095 if (ret < 0) {
21096 VERROR_INT("xmlSchemaValidateElemDecl",
21097 "calling xmlSchemaVCheckCVCSimpleType() to "
21098 "validate the attribute 'xsi:nil'");
21099 return (-1);
21100 }
21101 if (ret == 0) {
21102 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21103 /*
21104 * cvc-elt (3.3.4) : 3.1
21105 */
21106 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21107 "The element is not 'nillable'");
21108 /* Does not return an error on purpose. */
21109 } else {
21110 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21111 /*
21112 * cvc-elt (3.3.4) : 3.2.2
21113 */
21114 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21115 (elemDecl->value != NULL)) {
21116 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21117 "The element cannot be 'nilled' because "
21118 "there is a fixed value constraint defined "
21119 "for it");
21120 /* Does not return an error on purpose. */
21121 } else
21122 vctxt->inode->flags |=
21123 XML_SCHEMA_ELEM_INFO_NILLED;
21124 }
21125 }
21126 }
21127 }
21128 /*
21129 * cvc-elt (3.3.4) : 4
21130 * Handle 'xsi:type'.
21131 */
21132 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21133 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21134 if (iattr) {
21135 xmlSchemaTypePtr localType = NULL;
21136
21137 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21138 elemDecl);
21139 if (ret != 0) {
21140 if (ret == -1) {
21141 VERROR_INT("xmlSchemaValidateElemDecl",
21142 "calling xmlSchemaProcessXSIType() to "
21143 "process the attribute 'xsi:type'");
21144 return (-1);
21145 }
21146 /* Does not return an error on purpose. */
21147 }
21148 if (localType != NULL) {
21149 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21150 actualType = localType;
21151 }
21152 }
21153 }
21154 /*
21155 * IDC: Register identity-constraint XPath matchers.
21156 */
21157 if ((elemDecl->idcs != NULL) &&
21158 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21159 return (-1);
21160 /*
21161 * No actual type definition.
21162 */
21163 if (actualType == NULL) {
21164 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21165 "The type definition is absent");
21166 return (XML_SCHEMAV_CVC_TYPE_1);
21167 }
21168 /*
21169 * Remember the actual type definition.
21170 */
21171 vctxt->inode->typeDef = actualType;
21172
21173 return (0);
21174}
21175
21176static int
21177xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21178{
21179 xmlSchemaAttrInfoPtr iattr;
21180 int ret = 0, i;
21181
21182 /*
21183 * SPEC cvc-type (3.1.1)
21184 * "The attributes of must be empty, excepting those whose namespace
21185 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21186 * whose local name is one of type, nil, schemaLocation or
21187 * noNamespaceSchemaLocation."
21188 */
21189 if (vctxt->nbAttrInfos == 0)
21190 return (0);
21191 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21192 iattr = vctxt->attrInfos[i];
21193 if (! iattr->metaType) {
21194 ACTIVATE_ATTRIBUTE(iattr)
21195 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21196 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21197 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21198 }
21199 }
21200 ACTIVATE_ELEM
21201 return (ret);
21202}
21203
21204/*
21205* Cleanup currently used attribute infos.
21206*/
21207static void
21208xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21209{
21210 int i;
21211 xmlSchemaAttrInfoPtr attr;
21212
21213 if (vctxt->nbAttrInfos == 0)
21214 return;
21215 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21216 attr = vctxt->attrInfos[i];
21217 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21218 if (attr->localName != NULL)
21219 xmlFree((xmlChar *) attr->localName);
21220 if (attr->nsName != NULL)
21221 xmlFree((xmlChar *) attr->nsName);
21222 }
21223 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21224 if (attr->value != NULL)
21225 xmlFree((xmlChar *) attr->value);
21226 }
21227 if (attr->val != NULL) {
21228 xmlSchemaFreeValue(attr->val);
21229 attr->val = NULL;
21230 }
21231 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21232 }
21233 vctxt->nbAttrInfos = 0;
21234}
21235
21236/*
21237* 3.4.4 Complex Type Definition Validation Rules
21238* Element Locally Valid (Complex Type) (cvc-complex-type)
21239* 3.2.4 Attribute Declaration Validation Rules
21240* Validation Rule: Attribute Locally Valid (cvc-attribute)
21241* Attribute Locally Valid (Use) (cvc-au)
21242*
21243* Only "assessed" attribute information items will be visible to
21244* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21245*/
21246static int
21247xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21248{
21249 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21250 xmlSchemaAttributeLinkPtr attrUseLink;
21251 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21252 xmlSchemaAttrInfoPtr attr, tmpAttr;
21253 int i, found, nbAttrs;
21254 int xpathRes = 0, res, wildIDs = 0, fixed;
21255
21256 /*
21257 * SPEC (cvc-attribute)
21258 * (1) "The declaration must not be ·absent· (see Missing
21259 * Sub-components (§5.3) for how this can fail to be
21260 * the case)."
21261 * (2) "Its {type definition} must not be absent."
21262 *
21263 * NOTE (1) + (2): This is not handled here, since we currently do not
21264 * allow validation against schemas which have missing sub-components.
21265 *
21266 * SPEC (cvc-complex-type)
21267 * (3) "For each attribute information item in the element information
21268 * item's [attributes] excepting those whose [namespace name] is
21269 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21270 * [local name] is one of type, nil, schemaLocation or
21271 * noNamespaceSchemaLocation, the appropriate case among the following
21272 * must be true:
21273 *
21274 */
21275 nbAttrs = vctxt->nbAttrInfos;
21276 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21277 attrUseLink = attrUseLink->next) {
21278
21279 found = 0;
21280 attrUse = attrUseLink->attr;
21281 /*
21282 * VAL TODO: Implement a real "attribute use" component.
21283 */
21284 if (attrUse->refDecl != NULL)
21285 attrDecl = attrUse->refDecl;
21286 else
21287 attrDecl = attrUse;
21288 for (i = 0; i < nbAttrs; i++) {
21289 attr = vctxt->attrInfos[i];
21290 /*
21291 * SPEC (cvc-complex-type) (3)
21292 * Skip meta attributes.
21293 */
21294 if (attr->metaType)
21295 continue;
21296 if (attr->localName[0] != attrDecl->name[0])
21297 continue;
21298 if (!xmlStrEqual(attr->localName, attrDecl->name))
21299 continue;
21300 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21301 continue;
21302 found = 1;
21303 /*
21304 * SPEC (cvc-complex-type)
21305 * (3.1) "If there is among the {attribute uses} an attribute
21306 * use with an {attribute declaration} whose {name} matches
21307 * the attribute information item's [local name] and whose
21308 * {target namespace} is identical to the attribute information
21309 * item's [namespace name] (where an ·absent· {target namespace}
21310 * is taken to be identical to a [namespace name] with no value),
21311 * then the attribute information must be ·valid· with respect
21312 * to that attribute use as per Attribute Locally Valid (Use)
21313 * (§3.5.4). In this case the {attribute declaration} of that
21314 * attribute use is the ·context-determined declaration· for the
21315 * attribute information item with respect to Schema-Validity
21316 * Assessment (Attribute) (§3.2.4) and
21317 * Assessment Outcome (Attribute) (§3.2.5).
21318 */
21319 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21320 attr->use = attrUse;
21321 /*
21322 * Context-determined declaration.
21323 */
21324 attr->decl = attrDecl;
21325 attr->typeDef = attrDecl->subtypes;
21326 break;
21327 }
21328
21329 if (found)
21330 continue;
21331
21332 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21333 /*
21334 * Handle non-existent, required attributes.
21335 *
21336 * SPEC (cvc-complex-type)
21337 * (4) "The {attribute declaration} of each attribute use in
21338 * the {attribute uses} whose {required} is true matches one
21339 * of the attribute information items in the element information
21340 * item's [attributes] as per clause 3.1 above."
21341 */
21342 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21343 if (tmpAttr == NULL) {
21344 VERROR_INT(
21345 "xmlSchemaVAttributesComplex",
21346 "calling xmlSchemaGetFreshAttrInfo()");
21347 return (-1);
21348 }
21349 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21350 tmpAttr->use = attrUse;
21351 tmpAttr->decl = attrDecl;
21352 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21353 ((attrUse->defValue != NULL) ||
21354 (attrDecl->defValue != NULL))) {
21355 /*
21356 * Handle non-existent, optional, default/fixed attributes.
21357 */
21358 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21359 if (tmpAttr == NULL) {
21360 VERROR_INT(
21361 "xmlSchemaVAttributesComplex",
21362 "calling xmlSchemaGetFreshAttrInfo()");
21363 return (-1);
21364 }
21365 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21366 tmpAttr->use = attrUse;
21367 tmpAttr->decl = attrDecl;
21368 tmpAttr->typeDef = attrDecl->subtypes;
21369 tmpAttr->localName = attrDecl->name;
21370 tmpAttr->nsName = attrDecl->targetNamespace;
21371 }
21372 }
21373 if (vctxt->nbAttrInfos == 0)
21374 return (0);
21375 /*
21376 * Validate against the wildcard.
21377 */
21378 if (type->attributeWildcard != NULL) {
21379 /*
21380 * SPEC (cvc-complex-type)
21381 * (3.2.1) "There must be an {attribute wildcard}."
21382 */
21383 for (i = 0; i < nbAttrs; i++) {
21384 attr = vctxt->attrInfos[i];
21385 /*
21386 * SPEC (cvc-complex-type) (3)
21387 * Skip meta attributes.
21388 */
21389 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21390 continue;
21391 /*
21392 * SPEC (cvc-complex-type)
21393 * (3.2.2) "The attribute information item must be ·valid· with
21394 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21395 *
21396 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21397 * "... its [namespace name] must be ·valid· with respect to
21398 * the wildcard constraint, as defined in Wildcard allows
21399 * Namespace Name (§3.10.4)."
21400 */
21401 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21402 attr->nsName)) {
21403 /*
21404 * Handle processContents.
21405 *
21406 * SPEC (cvc-wildcard):
21407 * processContents | context-determined declaration:
21408 * "strict" "mustFind"
21409 * "lax" "none"
21410 * "skip" "skip"
21411 */
21412 if (type->attributeWildcard->processContents ==
21413 XML_SCHEMAS_ANY_SKIP) {
21414 /*
21415 * context-determined declaration = "skip"
21416 *
21417 * SPEC PSVI Assessment Outcome (Attribute)
21418 * [validity] = "notKnown"
21419 * [validation attempted] = "none"
21420 */
21421 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21422 continue;
21423 }
21424 /*
21425 * Find an attribute declaration.
21426 */
21427 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21428 attr->localName, attr->nsName);
21429 if (attr->decl != NULL) {
21430 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21431 /*
21432 * SPEC (cvc-complex-type)
21433 * (5) "Let [Definition:] the wild IDs be the set of
21434 * all attribute information item to which clause 3.2
21435 * applied and whose ·validation· resulted in a
21436 * ·context-determined declaration· of mustFind or no
21437 * ·context-determined declaration· at all, and whose
21438 * [local name] and [namespace name] resolve (as
21439 * defined by QName resolution (Instance) (§3.15.4)) to
21440 * an attribute declaration whose {type definition} is
21441 * or is derived from ID. Then all of the following
21442 * must be true:"
21443 */
21444 attr->typeDef = attr->decl->subtypes;
21445 if (xmlSchemaIsDerivedFromBuiltInType(
21446 attr->typeDef, XML_SCHEMAS_ID)) {
21447 /*
21448 * SPEC (5.1) "There must be no more than one
21449 * item in ·wild IDs·."
21450 */
21451 if (wildIDs != 0) {
21452 /* VAL TODO */
21453 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21454 TODO
21455 continue;
21456 }
21457 wildIDs++;
21458 /*
21459 * SPEC (cvc-complex-type)
21460 * (5.2) "If ·wild IDs· is non-empty, there must not
21461 * be any attribute uses among the {attribute uses}
21462 * whose {attribute declaration}'s {type definition}
21463 * is or is derived from ID."
21464 */
21465 for (attrUseLink = type->attributeUses;
21466 attrUseLink != NULL;
21467 attrUseLink = attrUseLink->next) {
21468 if (xmlSchemaIsDerivedFromBuiltInType(
21469 attrUseLink->attr->subtypes,
21470 XML_SCHEMAS_ID)) {
21471 /* VAL TODO */
21472 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21473 TODO
21474 }
21475 }
21476 }
21477 } else if (type->attributeWildcard->processContents ==
21478 XML_SCHEMAS_ANY_LAX) {
21479 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21480 /*
21481 * SPEC PSVI Assessment Outcome (Attribute)
21482 * [validity] = "notKnown"
21483 * [validation attempted] = "none"
21484 */
21485 } else {
21486 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21487 }
21488 }
21489 }
21490 }
21491
21492
21493 if (vctxt->nbAttrInfos == 0)
21494 return (0);
21495
21496 /*
21497 * Validate values, create default attributes, evaluate IDCs.
21498 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021499 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21500 attr = vctxt->attrInfos[i];
21501 /*
21502 * VAL TODO: Note that we won't try to resolve IDCs to
21503 * "lax" and "skip" validated attributes. Check what to
21504 * do in this case.
21505 */
21506 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21507 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21508 continue;
21509 /*
21510 * VAL TODO: What to do if the type definition is missing?
21511 */
21512 if (attr->typeDef == NULL) {
21513 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21514 continue;
21515 }
21516
21517 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021518 fixed = 0;
21519 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021520
21521 if (vctxt->xpathStates != NULL) {
21522 /*
21523 * Evaluate IDCs.
21524 */
21525 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21526 XML_ATTRIBUTE_NODE);
21527 if (xpathRes == -1) {
21528 VERROR_INT("xmlSchemaVAttributesComplex",
21529 "calling xmlSchemaXPathEvaluate()");
21530 goto internal_error;
21531 }
21532 }
21533
21534 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21535 /*
21536 * Default/fixed attributes.
21537 */
21538 if (xpathRes) {
21539 if (attr->use->defValue == NULL) {
21540 attr->value = (xmlChar *) attr->use->defValue;
21541 attr->val = attr->use->defVal;
21542 } else {
21543 attr->value = (xmlChar *) attr->decl->defValue;
21544 attr->val = attr->decl->defVal;
21545 }
21546 /*
21547 * IDCs will consume the precomputed default value,
21548 * so we need to clone it.
21549 */
21550 if (attr->val == NULL) {
21551 VERROR_INT("xmlSchemaVAttributesComplex",
21552 "default/fixed value on an attribute use was "
21553 "not precomputed");
21554 goto internal_error;
21555 }
21556 attr->val = xmlSchemaCopyValue(attr->val);
21557 if (attr->val == NULL) {
21558 VERROR_INT("xmlSchemaVAttributesComplex",
21559 "calling xmlSchemaCopyValue()");
21560 goto internal_error;
21561 }
21562 }
21563 /*
21564 * PSVI: Add the default attribute to the current element.
21565 * VAL TODO: Should we use the *normalized* value? This currently
21566 * uses the *initial* value.
21567 */
21568 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21569 (attr->node != NULL) && (attr->node->doc != NULL)) {
21570 xmlChar *normValue;
21571 const xmlChar *value;
21572
21573 value = attr->value;
21574 /*
21575 * Normalize the value.
21576 */
21577 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21578 attr->value);
21579 if (normValue != NULL)
21580 value = BAD_CAST normValue;
21581
21582 if (attr->nsName == NULL) {
21583 if (xmlNewProp(attr->node->parent,
21584 attr->localName, value) == NULL) {
21585 VERROR_INT("xmlSchemaVAttributesComplex",
21586 "callling xmlNewProp()");
21587 if (normValue != NULL)
21588 xmlFree(normValue);
21589 goto internal_error;
21590 }
21591 } else {
21592 xmlNsPtr ns;
21593
21594 ns = xmlSearchNsByHref(attr->node->doc,
21595 attr->node->parent, attr->nsName);
21596 if (ns == NULL) {
21597 xmlChar prefix[12];
21598 int counter = 0;
21599
21600 /*
21601 * Create a namespace declaration on the validation
21602 * root node if no namespace declaration is in scope.
21603 */
21604 do {
21605 snprintf((char *) prefix, 12, "p%d", counter++);
21606 ns = xmlSearchNs(attr->node->doc,
21607 attr->node->parent, BAD_CAST prefix);
21608 if (counter > 1000) {
21609 VERROR_INT(
21610 "xmlSchemaVAttributesComplex",
21611 "could not compute a ns prefix for a "
21612 "default/fixed attribute");
21613 if (normValue != NULL)
21614 xmlFree(normValue);
21615 goto internal_error;
21616 }
21617 } while (ns != NULL);
21618 ns = xmlNewNs(vctxt->validationRoot,
21619 attr->nsName, BAD_CAST prefix);
21620 }
21621 xmlNewNsProp(attr->node->parent, ns,
21622 attr->localName, value);
21623 }
21624 if (normValue != NULL)
21625 xmlFree(normValue);
21626 }
21627 /*
21628 * Go directly to IDC evaluation.
21629 */
21630 goto eval_idcs;
21631 }
21632 /*
21633 * Validate the value.
21634 */
21635 if (vctxt->value != NULL) {
21636 /*
21637 * Free last computed value; just for safety reasons.
21638 */
21639 xmlSchemaFreeValue(vctxt->value);
21640 vctxt->value = NULL;
21641 }
21642 /*
21643 * Note that the attribute *use* can be unavailable, if
21644 * the attribute was a wild attribute.
21645 */
21646 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21647 ((attr->use != NULL) &&
21648 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21649 fixed = 1;
21650 else
21651 fixed = 0;
21652 /*
21653 * SPEC (cvc-attribute)
21654 * (3) "The item's ·normalized value· must be locally ·valid·
21655 * with respect to that {type definition} as per
21656 * String Valid (§3.14.4)."
21657 *
21658 * VAL TODO: Do we already have the
21659 * "normalized attribute value" here?
21660 */
21661 if (xpathRes || fixed) {
21662 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21663 /*
21664 * Request a computed value.
21665 */
21666 res = xmlSchemaVCheckCVCSimpleType(
21667 (xmlSchemaAbstractCtxtPtr) vctxt,
21668 attr->node, attr->typeDef, attr->value, &(attr->val),
21669 1, 1, 0);
21670 } else {
21671 res = xmlSchemaVCheckCVCSimpleType(
21672 (xmlSchemaAbstractCtxtPtr) vctxt,
21673 attr->node, attr->typeDef, attr->value, NULL,
21674 1, 0, 0);
21675 }
21676
21677 if (res != 0) {
21678 if (res == -1) {
21679 VERROR_INT("xmlSchemaVAttributesComplex",
21680 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21681 goto internal_error;
21682 }
21683 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21684 /*
21685 * SPEC PSVI Assessment Outcome (Attribute)
21686 * [validity] = "invalid"
21687 */
21688 goto eval_idcs;
21689 }
21690
21691 if (fixed) {
21692 int ws;
21693 /*
21694 * SPEC Attribute Locally Valid (Use) (cvc-au)
21695 * "For an attribute information item to be·valid·
21696 * with respect to an attribute use its *normalized*
21697 * value· must match the *canonical* lexical
21698 * representation of the attribute use's {value
21699 * constraint}value, if it is present and fixed."
21700 *
21701 * VAL TODO: The requirement for the *canonical* value
21702 * will be removed in XML Schema 1.1.
21703 */
21704 /*
21705 * SPEC Attribute Locally Valid (cvc-attribute)
21706 * (4) "The item's *actual* value· must match the *value* of
21707 * the {value constraint}, if it is present and fixed."
21708 */
21709 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21710 if (attr->val == NULL) {
21711 /* VAL TODO: A value was not precomputed. */
21712 TODO
21713 goto eval_idcs;
21714 }
21715 if ((attr->use != NULL) &&
21716 (attr->use->defValue != NULL)) {
21717 if (attr->use->defVal == NULL) {
21718 /* VAL TODO: A default value was not precomputed. */
21719 TODO
21720 goto eval_idcs;
21721 }
21722 attr->vcValue = attr->use->defValue;
21723 /*
21724 if (xmlSchemaCompareValuesWhtsp(attr->val,
21725 (xmlSchemaWhitespaceValueType) ws,
21726 attr->use->defVal,
21727 (xmlSchemaWhitespaceValueType) ws) != 0) {
21728 */
21729 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21730 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21731 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021732 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021733 /* VAL TODO: A default value was not precomputed. */
21734 TODO
21735 goto eval_idcs;
21736 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021737 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021738 /*
21739 if (xmlSchemaCompareValuesWhtsp(attr->val,
21740 (xmlSchemaWhitespaceValueType) ws,
21741 attrDecl->defVal,
21742 (xmlSchemaWhitespaceValueType) ws) != 0) {
21743 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021744 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021745 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21746 }
21747 /*
21748 * [validity] = "valid"
21749 */
21750 }
21751eval_idcs:
21752 /*
21753 * Evaluate IDCs.
21754 */
21755 if (xpathRes) {
21756 if (xmlSchemaXPathProcessHistory(vctxt,
21757 vctxt->depth +1) == -1) {
21758 VERROR_INT("xmlSchemaVAttributesComplex",
21759 "calling xmlSchemaXPathEvaluate()");
21760 goto internal_error;
21761 }
21762 }
21763 }
21764
21765 /*
21766 * Report errors.
21767 */
21768 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21769 attr = vctxt->attrInfos[i];
21770 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21771 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21772 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21773 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21774 continue;
21775 ACTIVATE_ATTRIBUTE(attr);
21776 switch (attr->state) {
21777 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21778 xmlChar *str = NULL;
21779 ACTIVATE_ELEM;
21780 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21781 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21782 "The attribute '%s' is required but missing",
21783 xmlSchemaFormatQName(&str,
21784 attr->decl->targetNamespace,
21785 attr->decl->name),
21786 NULL);
21787 FREE_AND_NULL(str)
21788 break;
21789 }
21790 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21791 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21792 "The type definition is absent");
21793 break;
21794 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21795 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21796 XML_SCHEMAV_CVC_AU, NULL, NULL,
21797 "The value '%s' does not match the fixed "
21798 "value constraint '%s'",
21799 attr->value, attr->vcValue);
21800 break;
21801 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21802 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21803 "No matching global attribute declaration available, but "
21804 "demanded by the strict wildcard");
21805 break;
21806 case XML_SCHEMAS_ATTR_UNKNOWN:
21807 if (attr->metaType)
21808 break;
21809 /*
21810 * MAYBE VAL TODO: One might report different error messages
21811 * for the following errors.
21812 */
21813 if (type->attributeWildcard == NULL) {
21814 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21815 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21816 } else {
21817 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21818 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21819 }
21820 break;
21821 default:
21822 break;
21823 }
21824 }
21825
21826 ACTIVATE_ELEM;
21827 return (0);
21828internal_error:
21829 ACTIVATE_ELEM;
21830 return (-1);
21831}
21832
21833static int
21834xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21835 int *skip)
21836{
21837 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21838 /*
21839 * The namespace of the element was already identified to be
21840 * matching the wildcard.
21841 */
21842 if ((skip == NULL) || (wild == NULL) ||
21843 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21844 VERROR_INT("xmlSchemaValidateElemWildcard",
21845 "bad arguments");
21846 return (-1);
21847 }
21848 *skip = 0;
21849 if (wild->negNsSet != NULL) {
21850 /*
21851 * URGENT VAL TODO: Fix the content model to reject
21852 * "##other" wildcards.
21853 */
21854 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21855 vctxt->inode->nsName) != 0) {
21856 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21857 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21858 /*
21859 * VAL TODO: Workaround possible *only* if minOccurs and
21860 * maxOccurs are 1.
21861 */
21862 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21863 /* VAL TODO: error code? */
21864 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21865 (xmlSchemaTypePtr) wild,
21866 "This element is not accepted by the wildcard",
21867 0, 0, NULL);
21868 vctxt->skipDepth = vctxt->depth;
21869 if ((pinode->flags &
21870 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21871 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21872 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21873 return (XML_SCHEMAV_ELEMENT_CONTENT);
21874 }
21875 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21876 *skip = 1;
21877 return (0);
21878 }
21879 vctxt->inode->typeDef =
21880 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21881 return (0);
21882 }
21883 }
21884 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21885 /*
21886 * URGENT VAL TODO: Either we need to position the stream to the
21887 * next sibling, or walk the whole subtree.
21888 */
21889 *skip = 1;
21890 return (0);
21891 }
21892 {
21893 xmlSchemaElementPtr decl = NULL;
21894
21895 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21896 vctxt->inode->localName, vctxt->inode->nsName,
21897 NULL);
21898 if (decl != NULL) {
21899 vctxt->inode->decl = decl;
21900 return (0);
21901 }
21902 }
21903 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21904 /* VAL TODO: Change to proper error code. */
21905 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21906 "No matching global element declaration available, but "
21907 "demanded by the strict wildcard");
21908 return (vctxt->err);
21909 }
21910 if (vctxt->nbAttrInfos != 0) {
21911 xmlSchemaAttrInfoPtr iattr;
21912 /*
21913 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21914 * (1.2.1.2.1) - (1.2.1.2.3 )
21915 *
21916 * Use the xsi:type attribute for the type definition.
21917 */
21918 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21919 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21920 if (iattr != NULL) {
21921 if (xmlSchemaProcessXSIType(vctxt, iattr,
21922 &(vctxt->inode->typeDef), NULL) == -1) {
21923 VERROR_INT("xmlSchemaValidateElemWildcard",
21924 "calling xmlSchemaProcessXSIType() to "
21925 "process the attribute 'xsi:nil'");
21926 return (-1);
21927 }
21928 /*
21929 * Don't return an error on purpose.
21930 */
21931 return (0);
21932 }
21933 }
21934 /*
21935 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21936 *
21937 * Fallback to "anyType".
21938 */
21939 vctxt->inode->typeDef =
21940 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21941 return (0);
21942}
21943
21944/*
21945* xmlSchemaCheckCOSValidDefault:
21946*
21947* This will be called if: not nilled, no content and a default/fixed
21948* value is provided.
21949*/
21950
21951static int
21952xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21953 const xmlChar *value,
21954 xmlSchemaValPtr *val)
21955{
21956 int ret = 0;
21957 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21958
21959 /*
21960 * cos-valid-default:
21961 * Schema Component Constraint: Element Default Valid (Immediate)
21962 * For a string to be a valid default with respect to a type
21963 * definition the appropriate case among the following must be true:
21964 */
21965 if IS_COMPLEX_TYPE(inode->typeDef) {
21966 /*
21967 * Complex type.
21968 *
21969 * SPEC (2.1) "its {content type} must be a simple type definition
21970 * or mixed."
21971 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21972 * type}'s particle must be ·emptiable· as defined by
21973 * Particle Emptiable (§3.9.6)."
21974 */
21975 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21976 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21977 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21978 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21979 /* NOTE that this covers (2.2.2) as well. */
21980 VERROR(ret, NULL,
21981 "For a string to be a valid default, the type definition "
21982 "must be a simple type or a complex type with simple content "
21983 "or mixed content and a particle emptiable");
21984 return(ret);
21985 }
21986 }
21987 /*
21988 * 1 If the type definition is a simple type definition, then the string
21989 * must be ·valid· with respect to that definition as defined by String
21990 * Valid (§3.14.4).
21991 *
21992 * AND
21993 *
21994 * 2.2.1 If the {content type} is a simple type definition, then the
21995 * string must be ·valid· with respect to that simple type definition
21996 * as defined by String Valid (§3.14.4).
21997 */
21998 if (IS_SIMPLE_TYPE(inode->typeDef)) {
21999
22000 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22001 NULL, inode->typeDef, value, val, 1, 1, 0);
22002
22003 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22004
22005 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22006 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
22007 }
22008 if (ret < 0) {
22009 VERROR_INT("xmlSchemaCheckCOSValidDefault",
22010 "calling xmlSchemaVCheckCVCSimpleType()");
22011 }
22012 return (ret);
22013}
22014
22015static void
22016xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22017 const xmlChar * name ATTRIBUTE_UNUSED,
22018 xmlSchemaElementPtr item,
22019 xmlSchemaNodeInfoPtr inode)
22020{
22021 inode->decl = item;
22022#ifdef DEBUG_CONTENT
22023 {
22024 xmlChar *str = NULL;
22025
22026 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
22027 xmlGenericError(xmlGenericErrorContext,
22028 "AUTOMATON callback for '%s' [declaration]\n",
22029 xmlSchemaFormatQName(&str,
22030 inode->localName, inode->nsName));
22031 } else {
22032 xmlGenericError(xmlGenericErrorContext,
22033 "AUTOMATON callback for '%s' [wildcard]\n",
22034 xmlSchemaFormatQName(&str,
22035 inode->localName, inode->nsName));
22036
22037 }
22038 FREE_AND_NULL(str)
22039 }
22040#endif
22041}
22042
22043static int
22044xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022045{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022046 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22047 if (vctxt->inode == NULL) {
22048 VERROR_INT("xmlSchemaValidatorPushElem",
22049 "calling xmlSchemaGetFreshElemInfo()");
22050 return (-1);
22051 }
22052 vctxt->nbAttrInfos = 0;
22053 return (0);
22054}
22055
22056static int
22057xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22058 xmlSchemaNodeInfoPtr inode,
22059 xmlSchemaTypePtr type,
22060 const xmlChar *value)
22061{
22062 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22063 return (xmlSchemaVCheckCVCSimpleType(
22064 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22065 type, value, &(inode->val), 1, 1, 0));
22066 else
22067 return (xmlSchemaVCheckCVCSimpleType(
22068 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22069 type, value, NULL, 1, 0, 0));
22070}
22071
22072
22073
22074/*
22075* Process END of element.
22076*/
22077static int
22078xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22079{
22080 int ret = 0;
22081 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22082
22083 if (vctxt->nbAttrInfos != 0)
22084 xmlSchemaClearAttrInfos(vctxt);
22085 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22086 /*
22087 * This element was not expected;
22088 * we will not validate child elements of broken parents.
22089 * Skip validation of all content of the parent.
22090 */
22091 vctxt->skipDepth = vctxt->depth -1;
22092 goto end_elem;
22093 }
22094 if ((inode->typeDef == NULL) ||
22095 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22096 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022097 * 1. the type definition might be missing if the element was
22098 * error prone
22099 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022100 */
22101 goto end_elem;
22102 }
22103 /*
22104 * Check the content model.
22105 */
22106 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22107 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22108
22109 /*
22110 * Workaround for "anyType".
22111 */
22112 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22113 goto character_content;
22114
22115 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22116 xmlChar *values[10];
22117 int terminal, nbval = 10, nbneg;
22118
22119 if (inode->regexCtxt == NULL) {
22120 /*
22121 * Create the regex context.
22122 */
22123 inode->regexCtxt =
22124 xmlRegNewExecCtxt(inode->typeDef->contModel,
22125 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22126 vctxt);
22127 if (inode->regexCtxt == NULL) {
22128 VERROR_INT("xmlSchemaValidatorPopElem",
22129 "failed to create a regex context");
22130 goto internal_error;
22131 }
22132#ifdef DEBUG_AUTOMATA
22133 xmlGenericError(xmlGenericErrorContext,
22134 "AUTOMATON create on '%s'\n", inode->localName);
22135#endif
22136 }
22137 /*
22138 * Get hold of the still expected content, since a further
22139 * call to xmlRegExecPushString() will loose this information.
22140 */
22141 xmlRegExecNextValues(inode->regexCtxt,
22142 &nbval, &nbneg, &values[0], &terminal);
22143 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22144 if (ret <= 0) {
22145 /*
22146 * Still missing something.
22147 */
22148 ret = 1;
22149 inode->flags |=
22150 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22151 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22152 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22153 "Missing child element(s)",
22154 nbval, nbneg, values);
22155#ifdef DEBUG_AUTOMATA
22156 xmlGenericError(xmlGenericErrorContext,
22157 "AUTOMATON missing ERROR on '%s'\n",
22158 inode->localName);
22159#endif
22160 } else {
22161 /*
22162 * Content model is satisfied.
22163 */
22164 ret = 0;
22165#ifdef DEBUG_AUTOMATA
22166 xmlGenericError(xmlGenericErrorContext,
22167 "AUTOMATON succeeded on '%s'\n",
22168 inode->localName);
22169#endif
22170 }
22171
22172 }
22173 }
22174 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22175 goto end_elem;
22176
22177character_content:
22178
22179 if (vctxt->value != NULL) {
22180 xmlSchemaFreeValue(vctxt->value);
22181 vctxt->value = NULL;
22182 }
22183 /*
22184 * Check character content.
22185 */
22186 if (inode->decl == NULL) {
22187 /*
22188 * Speedup if no declaration exists.
22189 */
22190 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22191 ret = xmlSchemaVCheckINodeDataType(vctxt,
22192 inode, inode->typeDef, inode->value);
22193 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22194 ret = xmlSchemaVCheckINodeDataType(vctxt,
22195 inode, inode->typeDef->contentTypeDef,
22196 inode->value);
22197 }
22198 if (ret < 0) {
22199 VERROR_INT("xmlSchemaValidatorPopElem",
22200 "calling xmlSchemaVCheckCVCSimpleType()");
22201 goto internal_error;
22202 }
22203 goto end_elem;
22204 }
22205 /*
22206 * cvc-elt (3.3.4) : 5
22207 * The appropriate case among the following must be true:
22208 */
22209 /*
22210 * cvc-elt (3.3.4) : 5.1
22211 * If the declaration has a {value constraint},
22212 * the item has neither element nor character [children] and
22213 * clause 3.2 has not applied, then all of the following must be true:
22214 */
22215 if ((inode->decl->value != NULL) &&
22216 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22217 (! INODE_NILLED(inode))) {
22218 /*
22219 * cvc-elt (3.3.4) : 5.1.1
22220 * If the ·actual type definition· is a ·local type definition·
22221 * then the canonical lexical representation of the {value constraint}
22222 * value must be a valid default for the ·actual type definition· as
22223 * defined in Element Default Valid (Immediate) (§3.3.6).
22224 */
22225 /*
22226 * NOTE: 'local' above means types aquired by xsi:type.
22227 * NOTE: Although the *canonical* value is stated, it is not
22228 * relevant if canonical or not. Additionally XML Schema 1.1
22229 * will removed this requirement as well.
22230 */
22231 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22232
22233 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22234 inode->decl->value, &(inode->val));
22235 if (ret != 0) {
22236 if (ret < 0) {
22237 VERROR_INT("xmlSchemaValidatorPopElem",
22238 "calling xmlSchemaCheckCOSValidDefault()");
22239 goto internal_error;
22240 }
22241 goto end_elem;
22242 }
22243 /*
22244 * Stop here, to avoid redundant validation of the value
22245 * (see following).
22246 */
22247 goto default_psvi;
22248 }
22249 /*
22250 * cvc-elt (3.3.4) : 5.1.2
22251 * The element information item with the canonical lexical
22252 * representation of the {value constraint} value used as its
22253 * ·normalized value· must be ·valid· with respect to the
22254 * ·actual type definition· as defined by Element Locally Valid (Type)
22255 * (§3.3.4).
22256 */
22257 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22258 ret = xmlSchemaVCheckINodeDataType(vctxt,
22259 inode, inode->typeDef, inode->decl->value);
22260 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22261 ret = xmlSchemaVCheckINodeDataType(vctxt,
22262 inode, inode->typeDef->contentTypeDef,
22263 inode->decl->value);
22264 }
22265 if (ret != 0) {
22266 if (ret < 0) {
22267 VERROR_INT("xmlSchemaValidatorPopElem",
22268 "calling xmlSchemaVCheckCVCSimpleType()");
22269 goto internal_error;
22270 }
22271 goto end_elem;
22272 }
22273
22274default_psvi:
22275 /*
22276 * PSVI: Create a text node on the instance element.
22277 */
22278 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22279 (inode->node != NULL)) {
22280 xmlNodePtr textChild;
22281 xmlChar *normValue;
22282 /*
22283 * VAL TODO: Normalize the value.
22284 */
22285 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22286 inode->decl->value);
22287 if (normValue != NULL) {
22288 textChild = xmlNewText(BAD_CAST normValue);
22289 xmlFree(normValue);
22290 } else
22291 textChild = xmlNewText(inode->decl->value);
22292 if (textChild == NULL) {
22293 VERROR_INT("xmlSchemaValidatorPopElem",
22294 "calling xmlNewText()");
22295 goto internal_error;
22296 } else
22297 xmlAddChild(inode->node, textChild);
22298 }
22299
22300 } else if (! INODE_NILLED(inode)) {
22301 /*
22302 * 5.2.1 The element information item must be ·valid· with respect
22303 * to the ·actual type definition· as defined by Element Locally
22304 * Valid (Type) (§3.3.4).
22305 */
22306 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22307 /*
22308 * SPEC (cvc-type) (3.1)
22309 * "If the type definition is a simple type definition, ..."
22310 * (3.1.3) "If clause 3.2 of Element Locally Valid
22311 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22312 * must be ·valid· with respect to the type definition as defined
22313 * by String Valid (§3.14.4).
22314 */
22315 ret = xmlSchemaVCheckINodeDataType(vctxt,
22316 inode, inode->typeDef, inode->value);
22317 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22318 /*
22319 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22320 * definition, then the element information item must be
22321 * ·valid· with respect to the type definition as per
22322 * Element Locally Valid (Complex Type) (§3.4.4);"
22323 *
22324 * SPEC (cvc-complex-type) (2.2)
22325 * "If the {content type} is a simple type definition, ...
22326 * the ·normalized value· of the element information item is
22327 * ·valid· with respect to that simple type definition as
22328 * defined by String Valid (§3.14.4)."
22329 */
22330 ret = xmlSchemaVCheckINodeDataType(vctxt,
22331 inode, inode->typeDef->contentTypeDef, inode->value);
22332 }
22333 if (ret != 0) {
22334 if (ret < 0) {
22335 VERROR_INT("xmlSchemaValidatorPopElem",
22336 "calling xmlSchemaVCheckCVCSimpleType()");
22337 goto internal_error;
22338 }
22339 goto end_elem;
22340 }
22341 /*
22342 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22343 * not applied, all of the following must be true:
22344 */
22345 if ((inode->decl->value != NULL) &&
22346 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22347
22348 /*
22349 * TODO: We will need a computed value, when comparison is
22350 * done on computed values.
22351 */
22352 /*
22353 * 5.2.2.1 The element information item must have no element
22354 * information item [children].
22355 */
22356 if (inode->flags &
22357 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22358 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22359 VERROR(ret, NULL,
22360 "The content must not containt element nodes since "
22361 "there is a fixed value constraint");
22362 goto end_elem;
22363 } else {
22364 /*
22365 * 5.2.2.2 The appropriate case among the following must
22366 * be true:
22367 */
22368 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22369 /*
22370 * 5.2.2.2.1 If the {content type} of the ·actual type
22371 * definition· is mixed, then the *initial value* of the
22372 * item must match the canonical lexical representation
22373 * of the {value constraint} value.
22374 *
22375 * ... the *initial value* of an element information
22376 * item is the string composed of, in order, the
22377 * [character code] of each character information item in
22378 * the [children] of that element information item.
22379 */
22380 if (! xmlStrEqual(inode->value, inode->decl->value)){
22381 /*
22382 * VAL TODO: Report invalid & expected values as well.
22383 * VAL TODO: Implement the canonical stuff.
22384 */
22385 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22386 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22387 ret, NULL, NULL,
22388 "The initial value '%s' does not match the fixed "
22389 "value constraint '%s'",
22390 inode->value, inode->decl->value);
22391 goto end_elem;
22392 }
22393 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22394 /*
22395 * 5.2.2.2.2 If the {content type} of the ·actual type
22396 * definition· is a simple type definition, then the
22397 * *actual value* of the item must match the canonical
22398 * lexical representation of the {value constraint} value.
22399 */
22400 /*
22401 * VAL TODO: *actual value* is the normalized value, impl.
22402 * this.
22403 * VAL TODO: Report invalid & expected values as well.
22404 * VAL TODO: Implement a comparison with the computed values.
22405 */
22406 if (! xmlStrEqual(inode->value,
22407 inode->decl->value)) {
22408 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22409 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22410 ret, NULL, NULL,
22411 "The actual value '%s' does not match the fixed "
22412 "value constraint '%s'",
22413 inode->value,
22414 inode->decl->value);
22415 goto end_elem;
22416 }
22417 }
22418 }
22419 }
22420 }
22421
22422end_elem:
22423 if (vctxt->depth < 0) {
22424 /* TODO: raise error? */
22425 return (0);
22426 }
22427 if (vctxt->depth == vctxt->skipDepth)
22428 vctxt->skipDepth = -1;
22429 /*
22430 * Evaluate the history of XPath state objects.
22431 */
22432 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22433 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022434 /*
22435 * TODO: 6 The element information item must be ·valid· with respect to each of
22436 * the {identity-constraint definitions} as per Identity-constraint
22437 * Satisfied (§3.11.4).
22438 */
22439 /*
22440 * Validate IDC keyrefs.
22441 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022442 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22443 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022444 /*
22445 * Merge/free the IDC table.
22446 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022447 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022448#ifdef DEBUG_IDC
22449 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022450 inode->nsName,
22451 inode->localName,
22452 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022453#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022454 if (vctxt->depth > 0) {
22455 /*
22456 * Merge the IDC node table with the table of the parent node.
22457 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022458 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22459 goto internal_error;
22460 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022461 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022462 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022463 * Clear the current ielem.
22464 * VAL TODO: Don't free the PSVI IDC tables if they are
22465 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022466 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022467 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022468 /*
22469 * Skip further processing if we are on the validation root.
22470 */
22471 if (vctxt->depth == 0) {
22472 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022473 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022474 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022475 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022476 /*
22477 * Reset the bubbleDepth if needed.
22478 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022479 if (vctxt->aidcs != NULL) {
22480 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22481 do {
22482 if (aidc->bubbleDepth == vctxt->depth) {
22483 /*
22484 * A bubbleDepth of a key/unique IDC matches the current
22485 * depth, this means that we are leaving the scope of the
22486 * top-most keyref IDC.
22487 */
22488 aidc->bubbleDepth = -1;
22489 }
22490 aidc = aidc->next;
22491 } while (aidc != NULL);
22492 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022493 vctxt->depth--;
22494 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022495 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022496 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022497 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22498 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022499 return (ret);
22500
22501internal_error:
22502 vctxt->err = -1;
22503 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022504}
22505
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022506/*
22507* 3.4.4 Complex Type Definition Validation Rules
22508* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22509*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022510static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022511xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022512{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022513 xmlSchemaNodeInfoPtr pielem;
22514 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022515 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022516
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022517 if (vctxt->depth <= 0) {
22518 VERROR_INT("xmlSchemaValidateChildElem",
22519 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022520 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022521 }
22522 pielem = vctxt->elemInfos[vctxt->depth -1];
22523 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22524 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022525 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022526 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022527 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022528 if (INODE_NILLED(pielem)) {
22529 /*
22530 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22531 */
22532 ACTIVATE_PARENT_ELEM;
22533 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22534 VERROR(ret, NULL,
22535 "Neither character nor element content is allowed, "
22536 "because the element was 'nilled'");
22537 ACTIVATE_ELEM;
22538 goto unexpected_elem;
22539 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022540
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022541 ptype = pielem->typeDef;
22542
22543 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22544 /*
22545 * Workaround for "anyType": we have currently no content model
22546 * assigned for "anyType", so handle it explicitely.
22547 * "anyType" has an unbounded, lax "any" wildcard.
22548 */
22549 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22550 vctxt->inode->localName,
22551 vctxt->inode->nsName);
22552
22553 if (vctxt->inode->decl == NULL) {
22554 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022555 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022556 * Process "xsi:type".
22557 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022558 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022559 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22560 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22561 if (iattr != NULL) {
22562 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22563 &(vctxt->inode->typeDef), NULL);
22564 if (ret != 0) {
22565 if (ret == -1) {
22566 VERROR_INT("xmlSchemaValidateChildElem",
22567 "calling xmlSchemaProcessXSIType() to "
22568 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022569 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022570 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022571 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022572 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022573 } else {
22574 /*
22575 * Fallback to "anyType".
22576 *
22577 * SPEC (cvc-assess-elt)
22578 * "If the item cannot be ·strictly assessed·, [...]
22579 * an element information item's schema validity may be laxly
22580 * assessed if its ·context-determined declaration· is not
22581 * skip by ·validating· with respect to the ·ur-type
22582 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22583 */
22584 vctxt->inode->typeDef =
22585 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022586 }
22587 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022588 return (0);
22589 }
22590
22591 switch (ptype->contentType) {
22592 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022593 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022594 * SPEC (2.1) "If the {content type} is empty, then the
22595 * element information item has no character or element
22596 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022597 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022598 ACTIVATE_PARENT_ELEM
22599 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22600 VERROR(ret, NULL,
22601 "Element content is not allowed, "
22602 "because the content type is empty");
22603 ACTIVATE_ELEM
22604 goto unexpected_elem;
22605 break;
22606
22607 case XML_SCHEMA_CONTENT_MIXED:
22608 case XML_SCHEMA_CONTENT_ELEMENTS: {
22609 xmlRegExecCtxtPtr regexCtxt;
22610 xmlChar *values[10];
22611 int terminal, nbval = 10, nbneg;
22612
22613 /* VAL TODO: Optimized "anyType" validation.*/
22614
22615 if (ptype->contModel == NULL) {
22616 VERROR_INT("xmlSchemaValidateChildElem",
22617 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022618 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022619 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022620 /*
22621 * Safety belf for evaluation if the cont. model was already
22622 * examined to be invalid.
22623 */
22624 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22625 VERROR_INT("xmlSchemaValidateChildElem",
22626 "validating elem, but elem content is already invalid");
22627 return (-1);
22628 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022629
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022630 regexCtxt = pielem->regexCtxt;
22631 if (regexCtxt == NULL) {
22632 /*
22633 * Create the regex context.
22634 */
22635 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22636 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22637 vctxt);
22638 if (regexCtxt == NULL) {
22639 VERROR_INT("xmlSchemaValidateChildElem",
22640 "failed to create a regex context");
22641 return (-1);
22642 }
22643 pielem->regexCtxt = regexCtxt;
22644#ifdef DEBUG_AUTOMATA
22645 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22646 pielem->localName);
22647#endif
22648 }
22649
22650 /*
22651 * SPEC (2.4) "If the {content type} is element-only or mixed,
22652 * then the sequence of the element information item's
22653 * element information item [children], if any, taken in
22654 * order, is ·valid· with respect to the {content type}'s
22655 * particle, as defined in Element Sequence Locally Valid
22656 * (Particle) (§3.9.4)."
22657 */
22658 ret = xmlRegExecPushString2(regexCtxt,
22659 vctxt->inode->localName,
22660 vctxt->inode->nsName,
22661 vctxt->inode);
22662#ifdef DEBUG_AUTOMATA
22663 if (ret < 0)
22664 xmlGenericError(xmlGenericErrorContext,
22665 "AUTOMATON push ERROR for '%s' on '%s'\n",
22666 vctxt->inode->localName, pielem->localName);
22667 else
22668 xmlGenericError(xmlGenericErrorContext,
22669 "AUTOMATON push OK for '%s' on '%s'\n",
22670 vctxt->inode->localName, pielem->localName);
22671#endif
22672 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22673 VERROR_INT("xmlSchemaValidateChildElem",
22674 "calling xmlRegExecPushString2()");
22675 return (-1);
22676 }
22677 if (ret < 0) {
22678 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22679 &values[0], &terminal);
22680 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22681 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22682 "This element is not expected",
22683 nbval, nbneg, values);
22684 ret = vctxt->err;
22685 goto unexpected_elem;
22686 } else
22687 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022688 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022689 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022690 case XML_SCHEMA_CONTENT_SIMPLE:
22691 case XML_SCHEMA_CONTENT_BASIC:
22692 ACTIVATE_PARENT_ELEM
22693 if (IS_COMPLEX_TYPE(ptype)) {
22694 /*
22695 * SPEC (cvc-complex-type) (2.2)
22696 * "If the {content type} is a simple type definition, then
22697 * the element information item has no element information
22698 * item [children], ..."
22699 */
22700 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22701 VERROR(ret, NULL, "Element content is not allowed, "
22702 "because the content type is a simple type definition");
22703 } else {
22704 /*
22705 * SPEC (cvc-type) (3.1.2) "The element information item must
22706 * have no element information item [children]."
22707 */
22708 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22709 VERROR(ret, NULL, "Element content is not allowed, "
22710 "because the type definition is simple");
22711 }
22712 ACTIVATE_ELEM
22713 ret = vctxt->err;
22714 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022715 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022716
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022717 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022718 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022719 }
22720 return (ret);
22721unexpected_elem:
22722 /*
22723 * Pop this element and set the skipDepth to skip
22724 * all further content of the parent element.
22725 */
22726 vctxt->skipDepth = vctxt->depth;
22727 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22728 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22729 return (ret);
22730}
22731
22732#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22733#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22734#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22735
22736static int
22737xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22738 int nodeType, const xmlChar *value, int len,
22739 int mode, int *consumed)
22740{
22741 /*
22742 * Unfortunately we have to duplicate the text sometimes.
22743 * OPTIMIZE: Maybe we could skip it, if:
22744 * 1. content type is simple
22745 * 2. whitespace is "collapse"
22746 * 3. it consists of whitespace only
22747 *
22748 * Process character content.
22749 */
22750 if (consumed != NULL)
22751 *consumed = 0;
22752 if (INODE_NILLED(vctxt->inode)) {
22753 /*
22754 * SPEC cvc-elt (3.3.4 - 3.2.1)
22755 * "The element information item must have no character or
22756 * element information item [children]."
22757 */
22758 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22759 "Neither character nor element content is allowed "
22760 "because the element is 'nilled'");
22761 return (vctxt->err);
22762 }
22763 /*
22764 * SPEC (2.1) "If the {content type} is empty, then the
22765 * element information item has no character or element
22766 * information item [children]."
22767 */
22768 if (vctxt->inode->typeDef->contentType ==
22769 XML_SCHEMA_CONTENT_EMPTY) {
22770 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22771 "Character content is not allowed, "
22772 "because the content type is empty");
22773 return (vctxt->err);
22774 }
22775
22776 if (vctxt->inode->typeDef->contentType ==
22777 XML_SCHEMA_CONTENT_ELEMENTS) {
22778 if ((nodeType != XML_TEXT_NODE) ||
22779 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22780 /*
22781 * SPEC cvc-complex-type (2.3)
22782 * "If the {content type} is element-only, then the
22783 * element information item has no character information
22784 * item [children] other than those whose [character
22785 * code] is defined as a white space in [XML 1.0 (Second
22786 * Edition)]."
22787 */
22788 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22789 "Character content other than whitespace is not allowed "
22790 "because the content type is 'element-only'");
22791 return (vctxt->err);
22792 }
22793 return (0);
22794 }
22795
22796 if ((value == NULL) || (value[0] == 0))
22797 return (0);
22798 /*
22799 * Save the value.
22800 * NOTE that even if the content type is *mixed*, we need the
22801 * *initial value* for default/fixed value constraints.
22802 */
22803 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22804 ((vctxt->inode->decl == NULL) ||
22805 (vctxt->inode->decl->value == NULL)))
22806 return (0);
22807
22808 if (vctxt->inode->value == NULL) {
22809 /*
22810 * Set the value.
22811 */
22812 switch (mode) {
22813 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22814 /*
22815 * When working on a tree.
22816 */
22817 vctxt->inode->value = value;
22818 break;
22819 case XML_SCHEMA_PUSH_TEXT_CREATED:
22820 /*
22821 * When working with the reader.
22822 * The value will be freed by the element info.
22823 */
22824 vctxt->inode->value = value;
22825 if (consumed != NULL)
22826 *consumed = 1;
22827 vctxt->inode->flags |=
22828 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22829 break;
22830 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22831 /*
22832 * When working with SAX.
22833 * The value will be freed by the element info.
22834 */
22835 if (len != -1)
22836 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22837 else
22838 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22839 vctxt->inode->flags |=
22840 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22841 break;
22842 default:
22843 break;
22844 }
22845 } else {
22846 /*
22847 * Concat the value.
22848 */
22849 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022850 vctxt->inode->value = BAD_CAST xmlStrncat(
22851 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022852 } else {
22853 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022854 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022855 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22856 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022857 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022858
22859 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022860}
22861
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022862static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022863xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022864{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022865 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022866
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022867 if ((vctxt->skipDepth != -1) &&
22868 (vctxt->depth >= vctxt->skipDepth)) {
22869 VERROR_INT("xmlSchemaValidateElem",
22870 "in skip-state");
22871 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022872 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022873 if (vctxt->xsiAssemble) {
22874 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22875 goto internal_error;
22876 }
22877 if (vctxt->depth > 0) {
22878 /*
22879 * Validate this element against the content model
22880 * of the parent.
22881 */
22882 ret = xmlSchemaValidateChildElem(vctxt);
22883 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022884 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022885 VERROR_INT("xmlSchemaValidateElem",
22886 "calling xmlSchemaStreamValidateChildElement()");
22887 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022888 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022889 goto exit;
22890 }
22891 if (vctxt->depth == vctxt->skipDepth)
22892 goto exit;
22893 if ((vctxt->inode->decl == NULL) &&
22894 (vctxt->inode->typeDef == NULL)) {
22895 VERROR_INT("xmlSchemaValidateElem",
22896 "the child element was valid but neither the "
22897 "declaration nor the type was set");
22898 goto internal_error;
22899 }
22900 } else {
22901 /*
22902 * Get the declaration of the validation root.
22903 */
22904 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22905 vctxt->inode->localName,
22906 vctxt->inode->nsName);
22907 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022908 ret = XML_SCHEMAV_CVC_ELT_1;
22909 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022910 "No matching global declaration available "
22911 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022912 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022913 }
22914 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022915
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022916 if (vctxt->inode->decl == NULL)
22917 goto type_validation;
22918
22919 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22920 int skip;
22921 /*
22922 * Wildcards.
22923 */
22924 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22925 if (ret != 0) {
22926 if (ret < 0) {
22927 VERROR_INT("xmlSchemaValidateElem",
22928 "calling xmlSchemaValidateElemWildcard()");
22929 goto internal_error;
22930 }
22931 goto exit;
22932 }
22933 if (skip) {
22934 vctxt->skipDepth = vctxt->depth;
22935 goto exit;
22936 }
22937 /*
22938 * The declaration might be set by the wildcard validation,
22939 * when the processContents is "lax" or "strict".
22940 */
22941 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22942 /*
22943 * Clear the "decl" field to not confuse further processing.
22944 */
22945 vctxt->inode->decl = NULL;
22946 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022947 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022948 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022949 /*
22950 * Validate against the declaration.
22951 */
22952 ret = xmlSchemaValidateElemDecl(vctxt);
22953 if (ret != 0) {
22954 if (ret < 0) {
22955 VERROR_INT("xmlSchemaValidateElem",
22956 "calling xmlSchemaValidateElemDecl()");
22957 goto internal_error;
22958 }
22959 goto exit;
22960 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022961 /*
22962 * Validate against the type definition.
22963 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022964type_validation:
22965
22966 if (vctxt->inode->typeDef == NULL) {
22967 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22968 ret = XML_SCHEMAV_CVC_TYPE_1;
22969 VERROR(ret, NULL,
22970 "The type definition is absent");
22971 goto exit;
22972 }
22973 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22974 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22975 ret = XML_SCHEMAV_CVC_TYPE_2;
22976 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022977 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022978 goto exit;
22979 }
22980 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022981 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022982 * during validation against the declaration. This must be done
22983 * _before_ attribute validation.
22984 */
22985 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22986 if (ret == -1) {
22987 VERROR_INT("xmlSchemaValidateElem",
22988 "calling xmlSchemaXPathEvaluate()");
22989 goto internal_error;
22990 }
22991 /*
22992 * Validate attributes.
22993 */
22994 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22995 if ((vctxt->nbAttrInfos != 0) ||
22996 (vctxt->inode->typeDef->attributeUses != NULL)) {
22997
22998 ret = xmlSchemaVAttributesComplex(vctxt);
22999 }
23000 } else if (vctxt->nbAttrInfos != 0) {
23001
23002 ret = xmlSchemaVAttributesSimple(vctxt);
23003 }
23004 /*
23005 * Clear registered attributes.
23006 */
23007 if (vctxt->nbAttrInfos != 0)
23008 xmlSchemaClearAttrInfos(vctxt);
23009 if (ret == -1) {
23010 VERROR_INT("xmlSchemaValidateElem",
23011 "calling attributes validation");
23012 goto internal_error;
23013 }
23014 /*
23015 * Don't return an error if attributes are invalid on purpose.
23016 */
23017 ret = 0;
23018
23019exit:
23020 if (ret != 0)
23021 vctxt->skipDepth = vctxt->depth;
23022 return (ret);
23023internal_error:
23024 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023025}
23026
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023027#ifdef XML_SCHEMA_READER_ENABLED
23028static int
23029xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023030{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023031 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
23032 int depth, nodeType, ret = 0, consumed;
23033 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023034
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023035 vctxt->depth = -1;
23036 ret = xmlTextReaderRead(vctxt->reader);
23037 /*
23038 * Move to the document element.
23039 */
23040 while (ret == 1) {
23041 nodeType = xmlTextReaderNodeType(vctxt->reader);
23042 if (nodeType == XML_ELEMENT_NODE)
23043 goto root_found;
23044 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023045 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023046 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023047
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023048root_found:
23049
23050 do {
23051 depth = xmlTextReaderDepth(vctxt->reader);
23052 nodeType = xmlTextReaderNodeType(vctxt->reader);
23053
23054 if (nodeType == XML_ELEMENT_NODE) {
23055
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023056 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023057 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23058 VERROR_INT("xmlSchemaVReaderWalk",
23059 "calling xmlSchemaValidatorPushElem()");
23060 goto internal_error;
23061 }
23062 ielem = vctxt->inode;
23063 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23064 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23065 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23066 /*
23067 * Is the element empty?
23068 */
23069 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23070 if (ret == -1) {
23071 VERROR_INT("xmlSchemaVReaderWalk",
23072 "calling xmlTextReaderIsEmptyElement()");
23073 goto internal_error;
23074 }
23075 if (ret) {
23076 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23077 }
23078 /*
23079 * Register attributes.
23080 */
23081 vctxt->nbAttrInfos = 0;
23082 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23083 if (ret == -1) {
23084 VERROR_INT("xmlSchemaVReaderWalk",
23085 "calling xmlTextReaderMoveToFirstAttribute()");
23086 goto internal_error;
23087 }
23088 if (ret == 1) {
23089 do {
23090 /*
23091 * VAL TODO: How do we know that the reader works on a
23092 * node tree, to be able to pass a node here?
23093 */
23094 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23095 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23096 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23097 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23098
23099 VERROR_INT("xmlSchemaVReaderWalk",
23100 "calling xmlSchemaValidatorPushAttribute()");
23101 goto internal_error;
23102 }
23103 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23104 if (ret == -1) {
23105 VERROR_INT("xmlSchemaVReaderWalk",
23106 "calling xmlTextReaderMoveToFirstAttribute()");
23107 goto internal_error;
23108 }
23109 } while (ret == 1);
23110 /*
23111 * Back to element position.
23112 */
23113 ret = xmlTextReaderMoveToElement(vctxt->reader);
23114 if (ret == -1) {
23115 VERROR_INT("xmlSchemaVReaderWalk",
23116 "calling xmlTextReaderMoveToElement()");
23117 goto internal_error;
23118 }
23119 }
23120 /*
23121 * Validate the element.
23122 */
23123 ret= xmlSchemaValidateElem(vctxt);
23124 if (ret != 0) {
23125 if (ret == -1) {
23126 VERROR_INT("xmlSchemaVReaderWalk",
23127 "calling xmlSchemaValidateElem()");
23128 goto internal_error;
23129 }
23130 goto exit;
23131 }
23132 if (vctxt->depth == vctxt->skipDepth) {
23133 int curDepth;
23134 /*
23135 * Skip all content.
23136 */
23137 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23138 ret = xmlTextReaderRead(vctxt->reader);
23139 curDepth = xmlTextReaderDepth(vctxt->reader);
23140 while ((ret == 1) && (curDepth != depth)) {
23141 ret = xmlTextReaderRead(vctxt->reader);
23142 curDepth = xmlTextReaderDepth(vctxt->reader);
23143 }
23144 if (ret < 0) {
23145 /*
23146 * VAL TODO: A reader error occured; what to do here?
23147 */
23148 ret = 1;
23149 goto exit;
23150 }
23151 }
23152 goto leave_elem;
23153 }
23154 /*
23155 * READER VAL TODO: Is an END_ELEM really never called
23156 * if the elem is empty?
23157 */
23158 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23159 goto leave_elem;
23160 } else if (nodeType == END_ELEM) {
23161 /*
23162 * Process END of element.
23163 */
23164leave_elem:
23165 ret = xmlSchemaValidatorPopElem(vctxt);
23166 if (ret != 0) {
23167 if (ret < 0) {
23168 VERROR_INT("xmlSchemaVReaderWalk",
23169 "calling xmlSchemaValidatorPopElem()");
23170 goto internal_error;
23171 }
23172 goto exit;
23173 }
23174 if (vctxt->depth >= 0)
23175 ielem = vctxt->inode;
23176 else
23177 ielem = NULL;
23178 } else if ((nodeType == XML_TEXT_NODE) ||
23179 (nodeType == XML_CDATA_SECTION_NODE) ||
23180 (nodeType == WHTSP) ||
23181 (nodeType == SIGN_WHTSP)) {
23182 /*
23183 * Process character content.
23184 */
23185 xmlChar *value;
23186
23187 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23188 nodeType = XML_TEXT_NODE;
23189
23190 value = xmlTextReaderValue(vctxt->reader);
23191 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23192 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23193 if (! consumed)
23194 xmlFree(value);
23195 if (ret == -1) {
23196 VERROR_INT("xmlSchemaVReaderWalk",
23197 "calling xmlSchemaVPushText()");
23198 goto internal_error;
23199 }
23200 } else if ((nodeType == XML_ENTITY_NODE) ||
23201 (nodeType == XML_ENTITY_REF_NODE)) {
23202 /*
23203 * VAL TODO: What to do with entities?
23204 */
23205 TODO
23206 }
23207 /*
23208 * Read next node.
23209 */
23210 ret = xmlTextReaderRead(vctxt->reader);
23211 } while (ret == 1);
23212
23213exit:
23214 return (ret);
23215internal_error:
23216 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023217}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023218#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023219
23220/************************************************************************
23221 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023222 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023223 * *
23224 ************************************************************************/
23225
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023226#ifdef XML_SCHEMA_SAX_ENABLED
23227/*
23228* Process text content.
23229*/
23230static void
23231xmlSchemaSAXHandleText(void *ctx,
23232 const xmlChar * ch,
23233 int len)
23234{
23235 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23236
23237 if (vctxt->depth < 0)
23238 return;
23239 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23240 return;
23241 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23242 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23243 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23244 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23245 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23246 "calling xmlSchemaVPushText()");
23247 vctxt->err = -1;
23248 xmlStopParser(vctxt->parserCtxt);
23249 }
23250}
23251
23252/*
23253* Process CDATA content.
23254*/
23255static void
23256xmlSchemaSAXHandleCDataSection(void *ctx,
23257 const xmlChar * ch,
23258 int len)
23259{
23260 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23261
23262 if (vctxt->depth < 0)
23263 return;
23264 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23265 return;
23266 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23267 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23268 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23269 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23270 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23271 "calling xmlSchemaVPushText()");
23272 vctxt->err = -1;
23273 xmlStopParser(vctxt->parserCtxt);
23274 }
23275}
23276
23277static void
23278xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23279 const xmlChar * name ATTRIBUTE_UNUSED)
23280{
23281 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23282
23283 if (vctxt->depth < 0)
23284 return;
23285 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23286 return;
23287 /* SAX VAL TODO: What to do here? */
23288 TODO
23289}
23290
23291static void
23292xmlSchemaSAXHandleStartElementNs(void *ctx,
23293 const xmlChar * localname,
23294 const xmlChar * prefix ATTRIBUTE_UNUSED,
23295 const xmlChar * URI,
23296 int nb_namespaces,
23297 const xmlChar ** namespaces,
23298 int nb_attributes,
23299 int nb_defaulted ATTRIBUTE_UNUSED,
23300 const xmlChar ** attributes)
23301{
23302 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23303 int ret;
23304 xmlSchemaNodeInfoPtr ielem;
23305 int i, j;
23306
23307 /*
23308 * SAX VAL TODO: What to do with nb_defaulted?
23309 */
23310 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023311 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023312 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023313 vctxt->depth++;
23314 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023315 return;
23316 /*
23317 * Push the element.
23318 */
23319 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23320 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23321 "calling xmlSchemaValidatorPushElem()");
23322 goto internal_error;
23323 }
23324 ielem = vctxt->inode;
23325 ielem->localName = localname;
23326 ielem->nsName = URI;
23327 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23328 /*
23329 * Register namespaces on the elem info.
23330 */
23331 if (nb_namespaces != 0) {
23332 /*
23333 * Although the parser builds its own namespace list,
23334 * we have no access to it, so we'll use an own one.
23335 */
23336 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23337 /*
23338 * Store prefix and namespace name.
23339 */
23340 if (ielem->nsBindings == NULL) {
23341 ielem->nsBindings =
23342 (const xmlChar **) xmlMalloc(10 *
23343 sizeof(const xmlChar *));
23344 if (ielem->nsBindings == NULL) {
23345 xmlSchemaVErrMemory(vctxt,
23346 "allocating namespace bindings for SAX validation",
23347 NULL);
23348 goto internal_error;
23349 }
23350 ielem->nbNsBindings = 0;
23351 ielem->sizeNsBindings = 5;
23352 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23353 ielem->sizeNsBindings *= 2;
23354 ielem->nsBindings =
23355 (const xmlChar **) xmlRealloc(
23356 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023357 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023358 if (ielem->nsBindings == NULL) {
23359 xmlSchemaVErrMemory(vctxt,
23360 "re-allocating namespace bindings for SAX validation",
23361 NULL);
23362 goto internal_error;
23363 }
23364 }
23365
23366 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23367 if (namespaces[j+1][0] == 0) {
23368 /*
23369 * Handle xmlns="".
23370 */
23371 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23372 } else
23373 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23374 namespaces[j+1];
23375 ielem->nbNsBindings++;
23376 }
23377 }
23378 /*
23379 * Register attributes.
23380 * SAX VAL TODO: We are not adding namespace declaration
23381 * attributes yet.
23382 */
23383 if (nb_attributes != 0) {
23384 xmlChar *value;
23385
23386 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23387 /*
23388 * Duplicate the value.
23389 */
23390 value = xmlStrndup(attributes[j+3],
23391 attributes[j+4] - attributes[j+3]);
23392 ret = xmlSchemaValidatorPushAttribute(vctxt,
23393 NULL, attributes[j], attributes[j+2], 0,
23394 value, 1);
23395 if (ret == -1) {
23396 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23397 "calling xmlSchemaValidatorPushAttribute()");
23398 goto internal_error;
23399 }
23400 }
23401 }
23402 /*
23403 * Validate the element.
23404 */
23405 ret = xmlSchemaValidateElem(vctxt);
23406 if (ret != 0) {
23407 if (ret == -1) {
23408 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23409 "calling xmlSchemaValidateElem()");
23410 goto internal_error;
23411 }
23412 goto exit;
23413 }
23414
23415exit:
23416 return;
23417internal_error:
23418 vctxt->err = -1;
23419 xmlStopParser(vctxt->parserCtxt);
23420 return;
23421}
23422
23423static void
23424xmlSchemaSAXHandleEndElementNs(void *ctx,
23425 const xmlChar * localname ATTRIBUTE_UNUSED,
23426 const xmlChar * prefix ATTRIBUTE_UNUSED,
23427 const xmlChar * URI ATTRIBUTE_UNUSED)
23428{
23429 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23430 int res;
23431
23432 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023433 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023434 */
23435 if (vctxt->skipDepth != -1) {
23436 if (vctxt->depth > vctxt->skipDepth) {
23437 vctxt->depth--;
23438 return;
23439 } else
23440 vctxt->skipDepth = -1;
23441 }
23442 /*
23443 * SAX VAL TODO: Just a temporary check.
23444 */
23445 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23446 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23447 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23448 "elem pop mismatch");
23449 }
23450 res = xmlSchemaValidatorPopElem(vctxt);
23451 if (res != 0) {
23452 if (res < 0) {
23453 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23454 "calling xmlSchemaValidatorPopElem()");
23455 goto internal_error;
23456 }
23457 goto exit;
23458 }
23459exit:
23460 return;
23461internal_error:
23462 vctxt->err = -1;
23463 xmlStopParser(vctxt->parserCtxt);
23464 return;
23465}
23466#endif
23467
Daniel Veillard4255d502002-04-16 15:50:10 +000023468/************************************************************************
23469 * *
23470 * Validation interfaces *
23471 * *
23472 ************************************************************************/
23473
23474/**
23475 * xmlSchemaNewValidCtxt:
23476 * @schema: a precompiled XML Schemas
23477 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023478 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023479 *
23480 * Returns the validation context or NULL in case of error
23481 */
23482xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023483xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23484{
Daniel Veillard4255d502002-04-16 15:50:10 +000023485 xmlSchemaValidCtxtPtr ret;
23486
23487 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23488 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023489 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023490 return (NULL);
23491 }
23492 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023493 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23494 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023495 return (ret);
23496}
23497
23498/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023499 * xmlSchemaClearValidCtxt:
23500 * @ctxt: the schema validation context
23501 *
23502 * Free the resources associated to the schema validation context;
23503 * leaves some fields alive intended for reuse of the context.
23504 */
23505static void
23506xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23507{
23508 if (vctxt == NULL)
23509 return;
23510
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023511 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023512 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023513 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023514#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023515 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023516#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023517 if (vctxt->value != NULL) {
23518 xmlSchemaFreeValue(vctxt->value);
23519 vctxt->value = NULL;
23520 }
23521 /*
23522 * Augmented IDC information.
23523 */
23524 if (vctxt->aidcs != NULL) {
23525 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23526 do {
23527 next = cur->next;
23528 xmlFree(cur);
23529 cur = next;
23530 } while (cur != NULL);
23531 vctxt->aidcs = NULL;
23532 }
23533 if (vctxt->idcNodes != NULL) {
23534 int i;
23535 xmlSchemaPSVIIDCNodePtr item;
23536
23537 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023538 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023539 xmlFree(item->keys);
23540 xmlFree(item);
23541 }
23542 xmlFree(vctxt->idcNodes);
23543 vctxt->idcNodes = NULL;
23544 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023545 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023546 * Note that we won't delete the XPath state pool here.
23547 */
23548 if (vctxt->xpathStates != NULL) {
23549 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23550 vctxt->xpathStates = NULL;
23551 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023552 /*
23553 * Attribute info.
23554 */
23555 if (vctxt->nbAttrInfos != 0) {
23556 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023557 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023558 /*
23559 * Element info.
23560 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023561 if (vctxt->elemInfos != NULL) {
23562 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023563 xmlSchemaNodeInfoPtr ei;
23564
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023565 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023566 ei = vctxt->elemInfos[i];
23567 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023568 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023569 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023570 }
23571 }
23572}
23573
23574/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023575 * xmlSchemaFreeValidCtxt:
23576 * @ctxt: the schema validation context
23577 *
23578 * Free the resources associated to the schema validation context
23579 */
23580void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023581xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23582{
Daniel Veillard4255d502002-04-16 15:50:10 +000023583 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023584 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023585 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023586 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023587 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023588 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023589 if (ctxt->idcNodes != NULL) {
23590 int i;
23591 xmlSchemaPSVIIDCNodePtr item;
23592
23593 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023594 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023595 xmlFree(item->keys);
23596 xmlFree(item);
23597 }
23598 xmlFree(ctxt->idcNodes);
23599 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023600 if (ctxt->idcKeys != NULL) {
23601 int i;
23602 for (i = 0; i < ctxt->nbIdcKeys; i++)
23603 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23604 xmlFree(ctxt->idcKeys);
23605 }
23606
23607 if (ctxt->xpathStates != NULL)
23608 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23609 if (ctxt->xpathStatePool != NULL)
23610 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23611
23612 /*
23613 * Augmented IDC information.
23614 */
23615 if (ctxt->aidcs != NULL) {
23616 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23617 do {
23618 next = cur->next;
23619 xmlFree(cur);
23620 cur = next;
23621 } while (cur != NULL);
23622 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023623 if (ctxt->attrInfos != NULL) {
23624 int i;
23625 xmlSchemaAttrInfoPtr attr;
23626
23627 /* Just a paranoid call to the cleanup. */
23628 if (ctxt->nbAttrInfos != 0)
23629 xmlSchemaClearAttrInfos(ctxt);
23630 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23631 attr = ctxt->attrInfos[i];
23632 xmlFree(attr);
23633 }
23634 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023635 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023636 if (ctxt->elemInfos != NULL) {
23637 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023638 xmlSchemaNodeInfoPtr ei;
23639
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023640 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023641 ei = ctxt->elemInfos[i];
23642 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023643 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023644 xmlSchemaClearElemInfo(ei);
23645 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023646 }
23647 xmlFree(ctxt->elemInfos);
23648 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023649 if (ctxt->dict != NULL)
23650 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023651 xmlFree(ctxt);
23652}
23653
23654/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000023655 * xmlSchemaIsValid:
23656 * @ctxt: the schema validation context
23657 *
23658 * Check if any error was detected during validation.
23659 *
23660 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
23661 * of internal error.
23662 */
23663int
23664xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
23665{
23666 if (ctxt == NULL)
23667 return(-1);
23668 return(ctxt->err == 0);
23669}
23670
23671/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023672 * xmlSchemaSetValidErrors:
23673 * @ctxt: a schema validation context
23674 * @err: the error function
23675 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023676 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023677 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023678 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023679 */
23680void
23681xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023682 xmlSchemaValidityErrorFunc err,
23683 xmlSchemaValidityWarningFunc warn, void *ctx)
23684{
Daniel Veillard4255d502002-04-16 15:50:10 +000023685 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023686 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023687 ctxt->error = err;
23688 ctxt->warning = warn;
23689 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023690 if (ctxt->pctxt != NULL)
23691 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023692}
23693
23694/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000023695 * xmlSchemaSetValidStructuredErrors:
23696 * @ctxt: a schema validation context
23697 * @serror: the structured error function
23698 * @ctx: the functions context
23699 *
23700 * Set the structured error callback
23701 */
23702void
23703xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
23704 xmlStructuredErrorFunc serror, void *ctx)
23705{
23706 if (ctxt == NULL)
23707 return;
23708 ctxt->serror = serror;
23709 ctxt->error = NULL;
23710 ctxt->warning = NULL;
23711 ctxt->userData = ctx;
23712}
23713
23714/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023715 * xmlSchemaGetValidErrors:
23716 * @ctxt: a XML-Schema validation context
23717 * @err: the error function result
23718 * @warn: the warning function result
23719 * @ctx: the functions context result
23720 *
23721 * Get the error and warning callback informations
23722 *
23723 * Returns -1 in case of error and 0 otherwise
23724 */
23725int
23726xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23727 xmlSchemaValidityErrorFunc * err,
23728 xmlSchemaValidityWarningFunc * warn, void **ctx)
23729{
23730 if (ctxt == NULL)
23731 return (-1);
23732 if (err != NULL)
23733 *err = ctxt->error;
23734 if (warn != NULL)
23735 *warn = ctxt->warning;
23736 if (ctx != NULL)
23737 *ctx = ctxt->userData;
23738 return (0);
23739}
23740
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023741
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023742/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023743 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023744 * @ctxt: a schema validation context
23745 * @options: a combination of xmlSchemaValidOption
23746 *
23747 * Sets the options to be used during the validation.
23748 *
23749 * Returns 0 in case of success, -1 in case of an
23750 * API error.
23751 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023752int
23753xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23754 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023755
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023756{
23757 int i;
23758
23759 if (ctxt == NULL)
23760 return (-1);
23761 /*
23762 * WARNING: Change the start value if adding to the
23763 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023764 * TODO: Is there an other, more easy to maintain,
23765 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023766 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023767 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023768 if (options & 1<<i)
23769 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023770 }
23771 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023772 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023773}
23774
23775/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023776 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023777 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023778 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023779 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023780 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023781 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023782 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023783int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023784xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023785
23786{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023787 if (ctxt == NULL)
23788 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023789 else
23790 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023791}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023792
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023793static int
23794xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23795{
23796 xmlAttrPtr attr;
23797 int ret = 0;
23798 xmlSchemaNodeInfoPtr ielem = NULL;
23799 xmlNodePtr node, valRoot;
23800 const xmlChar *nsName;
23801
23802 /* DOC VAL TODO: Move this to the start function. */
23803 valRoot = xmlDocGetRootElement(vctxt->doc);
23804 if (valRoot == NULL) {
23805 /* VAL TODO: Error code? */
23806 VERROR(1, NULL, "The document has no document element");
23807 return (1);
23808 }
23809 vctxt->depth = -1;
23810 vctxt->validationRoot = valRoot;
23811 node = valRoot;
23812 while (node != NULL) {
23813 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23814 goto next_sibling;
23815 if (node->type == XML_ELEMENT_NODE) {
23816
23817 /*
23818 * Init the node-info.
23819 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023820 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023821 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23822 goto internal_error;
23823 ielem = vctxt->inode;
23824 ielem->node = node;
23825 ielem->localName = node->name;
23826 if (node->ns != NULL)
23827 ielem->nsName = node->ns->href;
23828 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23829 /*
23830 * Register attributes.
23831 * DOC VAL TODO: We do not register namespace declaration
23832 * attributes yet.
23833 */
23834 vctxt->nbAttrInfos = 0;
23835 if (node->properties != NULL) {
23836 attr = node->properties;
23837 do {
23838 if (attr->ns != NULL)
23839 nsName = attr->ns->href;
23840 else
23841 nsName = NULL;
23842 ret = xmlSchemaValidatorPushAttribute(vctxt,
23843 (xmlNodePtr) attr,
23844 attr->name, nsName, 0,
23845 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23846 if (ret == -1) {
23847 VERROR_INT("xmlSchemaDocWalk",
23848 "calling xmlSchemaValidatorPushAttribute()");
23849 goto internal_error;
23850 }
23851 attr = attr->next;
23852 } while (attr);
23853 }
23854 /*
23855 * Validate the element.
23856 */
23857 ret = xmlSchemaValidateElem(vctxt);
23858 if (ret != 0) {
23859 if (ret == -1) {
23860 VERROR_INT("xmlSchemaDocWalk",
23861 "calling xmlSchemaValidateElem()");
23862 goto internal_error;
23863 }
23864 /*
23865 * Don't stop validation; just skip the content
23866 * of this element.
23867 */
23868 goto leave_node;
23869 }
23870 if ((vctxt->skipDepth != -1) &&
23871 (vctxt->depth >= vctxt->skipDepth))
23872 goto leave_node;
23873 } else if ((node->type == XML_TEXT_NODE) ||
23874 (node->type == XML_CDATA_SECTION_NODE)) {
23875 /*
23876 * Process character content.
23877 */
23878 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23879 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23880 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23881 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23882 if (ret < 0) {
23883 VERROR_INT("xmlSchemaVDocWalk",
23884 "calling xmlSchemaVPushText()");
23885 goto internal_error;
23886 }
23887 /*
23888 * DOC VAL TODO: Should we skip further validation of the
23889 * element content here?
23890 */
23891 } else if ((node->type == XML_ENTITY_NODE) ||
23892 (node->type == XML_ENTITY_REF_NODE)) {
23893 /*
23894 * DOC VAL TODO: What to do with entities?
23895 */
23896 TODO
23897 } else {
23898 goto leave_node;
23899 /*
23900 * DOC VAL TODO: XInclude nodes, etc.
23901 */
23902 }
23903 /*
23904 * Walk the doc.
23905 */
23906 if (node->children != NULL) {
23907 node = node->children;
23908 continue;
23909 }
23910leave_node:
23911 if (node->type == XML_ELEMENT_NODE) {
23912 /*
23913 * Leaving the scope of an element.
23914 */
23915 if (node != vctxt->inode->node) {
23916 VERROR_INT("xmlSchemaVDocWalk",
23917 "element position mismatch");
23918 goto internal_error;
23919 }
23920 ret = xmlSchemaValidatorPopElem(vctxt);
23921 if (ret != 0) {
23922 if (ret < 0) {
23923 VERROR_INT("xmlSchemaVDocWalk",
23924 "calling xmlSchemaValidatorPopElem()");
23925 goto internal_error;
23926 }
23927 }
23928 if (node == valRoot)
23929 goto exit;
23930 }
23931next_sibling:
23932 if (node->next != NULL)
23933 node = node->next;
23934 else {
23935 node = node->parent;
23936 goto leave_node;
23937 }
23938 }
23939
23940exit:
23941 return (ret);
23942internal_error:
23943 return (-1);
23944}
23945
23946static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000023947xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023948 /*
23949 * Some initialization.
23950 */
23951 vctxt->err = 0;
23952 vctxt->nberrors = 0;
23953 vctxt->depth = -1;
23954 vctxt->skipDepth = -1;
23955 /*
23956 * Create a schema + parser if necessary.
23957 */
23958 if (vctxt->schema == NULL) {
23959
23960 if ((vctxt->pctxt == NULL) &&
23961 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23962 return (-1);
23963
23964 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23965 if (vctxt->schema == NULL) {
23966 VERROR_INT("xmlSchemaVStartValidation",
23967 "creating a schema");
23968 return (-1);
23969 }
23970 vctxt->xsiAssemble = 1;
23971 } else
23972 vctxt->xsiAssemble = 0;
23973 /*
23974 * Augment the IDC definitions.
23975 */
23976 if (vctxt->schema->idcDef != NULL) {
23977 xmlHashScan(vctxt->schema->idcDef,
23978 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23979 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000023980 return(0);
23981}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023982
Daniel Veillardf10ae122005-07-10 19:03:16 +000023983static void
23984xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023985 if (vctxt->xsiAssemble) {
23986 if (vctxt->schema != NULL) {
23987 xmlSchemaFree(vctxt->schema);
23988 vctxt->schema = NULL;
23989 }
23990 }
23991 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000023992}
23993
23994static int
23995xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23996{
23997 int ret = 0;
23998
23999 if (xmlSchemaPreRun(vctxt) < 0)
24000 return(-1);
24001
24002 if (vctxt->doc != NULL) {
24003 /*
24004 * Tree validation.
24005 */
24006 ret = xmlSchemaVDocWalk(vctxt);
24007#ifdef LIBXML_READER_ENABLED
24008 } else if (vctxt->reader != NULL) {
24009 /*
24010 * XML Reader validation.
24011 */
24012#ifdef XML_SCHEMA_READER_ENABLED
24013 ret = xmlSchemaVReaderWalk(vctxt);
24014#endif
24015#endif
24016 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
24017 /*
24018 * SAX validation.
24019 */
24020 ret = xmlParseDocument(vctxt->parserCtxt);
24021 } else {
24022 VERROR_INT("xmlSchemaVStartValidation",
24023 "no instance to validate");
24024 ret = -1;
24025 }
24026
24027 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024028 if (ret == 0)
24029 ret = vctxt->err;
24030 return (ret);
24031}
24032
24033/**
24034 * xmlSchemaValidateOneElement:
24035 * @ctxt: a schema validation context
24036 * @elem: an element node
24037 *
24038 * Validate a branch of a tree, starting with the given @elem.
24039 *
24040 * Returns 0 if the element and its subtree is valid, a positive error
24041 * code number otherwise and -1 in case of an internal or API error.
24042 */
24043int
24044xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24045{
24046 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24047 return (-1);
24048
24049 if (ctxt->schema == NULL)
24050 return (-1);
24051
24052 ctxt->doc = elem->doc;
24053 ctxt->node = elem;
24054 ctxt->validationRoot = elem;
24055 return(xmlSchemaVStart(ctxt));
24056}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024057
Daniel Veillard259f0df2004-08-18 09:13:18 +000024058/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024059 * xmlSchemaValidateDoc:
24060 * @ctxt: a schema validation context
24061 * @doc: a parsed document tree
24062 *
24063 * Validate a document tree in memory.
24064 *
24065 * Returns 0 if the document is schemas valid, a positive error code
24066 * number otherwise and -1 in case of internal or API error.
24067 */
24068int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024069xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24070{
Daniel Veillard4255d502002-04-16 15:50:10 +000024071 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024072 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024073
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024074 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024075 ctxt->node = xmlDocGetRootElement(doc);
24076 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024077 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024078 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24079 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024080 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024081 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024082 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024083 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024084 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024085}
24086
Daniel Veillardcdc82732005-07-08 15:04:06 +000024087
24088/************************************************************************
24089 * *
24090 * Function and data for SAX streaming API *
24091 * *
24092 ************************************************************************/
24093typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24094typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24095
24096struct _xmlSchemaSplitSAXData {
24097 xmlSAXHandlerPtr user_sax;
24098 void *user_data;
24099 xmlSchemaValidCtxtPtr ctxt;
24100 xmlSAXHandlerPtr schemas_sax;
24101};
24102
Daniel Veillard971771e2005-07-09 17:32:57 +000024103#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24104
24105struct _xmlSchemaSAXPlug {
24106 unsigned int magic;
24107
24108 /* the original callbacks informations */
24109 xmlSAXHandlerPtr *user_sax_ptr;
24110 xmlSAXHandlerPtr user_sax;
24111 void **user_data_ptr;
24112 void *user_data;
24113
24114 /* the block plugged back and validation informations */
24115 xmlSAXHandler schemas_sax;
24116 xmlSchemaValidCtxtPtr ctxt;
24117};
24118
Daniel Veillardcdc82732005-07-08 15:04:06 +000024119/* All those functions just bounces to the user provided SAX handlers */
24120static void
24121internalSubsetSplit(void *ctx, const xmlChar *name,
24122 const xmlChar *ExternalID, const xmlChar *SystemID)
24123{
Daniel Veillard971771e2005-07-09 17:32:57 +000024124 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024125 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24126 (ctxt->user_sax->internalSubset != NULL))
24127 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24128 SystemID);
24129}
24130
24131static int
24132isStandaloneSplit(void *ctx)
24133{
Daniel Veillard971771e2005-07-09 17:32:57 +000024134 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024135 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24136 (ctxt->user_sax->isStandalone != NULL))
24137 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24138 return(0);
24139}
24140
24141static int
24142hasInternalSubsetSplit(void *ctx)
24143{
Daniel Veillard971771e2005-07-09 17:32:57 +000024144 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024145 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24146 (ctxt->user_sax->hasInternalSubset != NULL))
24147 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24148 return(0);
24149}
24150
24151static int
24152hasExternalSubsetSplit(void *ctx)
24153{
Daniel Veillard971771e2005-07-09 17:32:57 +000024154 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024155 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24156 (ctxt->user_sax->hasExternalSubset != NULL))
24157 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24158 return(0);
24159}
24160
24161static void
24162externalSubsetSplit(void *ctx, const xmlChar *name,
24163 const xmlChar *ExternalID, const xmlChar *SystemID)
24164{
Daniel Veillard971771e2005-07-09 17:32:57 +000024165 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024166 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24167 (ctxt->user_sax->internalSubset != NULL))
24168 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24169 SystemID);
24170}
24171
24172static xmlParserInputPtr
24173resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24174{
Daniel Veillard971771e2005-07-09 17:32:57 +000024175 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024176 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24177 (ctxt->user_sax->resolveEntity != NULL))
24178 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24179 systemId));
24180 return(NULL);
24181}
24182
24183static xmlEntityPtr
24184getEntitySplit(void *ctx, const xmlChar *name)
24185{
Daniel Veillard971771e2005-07-09 17:32:57 +000024186 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024187 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24188 (ctxt->user_sax->getEntity != NULL))
24189 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24190 return(NULL);
24191}
24192
24193static xmlEntityPtr
24194getParameterEntitySplit(void *ctx, const xmlChar *name)
24195{
Daniel Veillard971771e2005-07-09 17:32:57 +000024196 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024197 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24198 (ctxt->user_sax->getParameterEntity != NULL))
24199 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24200 return(NULL);
24201}
24202
24203
24204static void
24205entityDeclSplit(void *ctx, const xmlChar *name, int type,
24206 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24207{
Daniel Veillard971771e2005-07-09 17:32:57 +000024208 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024209 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24210 (ctxt->user_sax->entityDecl != NULL))
24211 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24212 systemId, content);
24213}
24214
24215static void
24216attributeDeclSplit(void *ctx, const xmlChar * elem,
24217 const xmlChar * name, int type, int def,
24218 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24219{
Daniel Veillard971771e2005-07-09 17:32:57 +000024220 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024221 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24222 (ctxt->user_sax->attributeDecl != NULL)) {
24223 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24224 def, defaultValue, tree);
24225 } else {
24226 xmlFreeEnumeration(tree);
24227 }
24228}
24229
24230static void
24231elementDeclSplit(void *ctx, const xmlChar *name, int type,
24232 xmlElementContentPtr content)
24233{
Daniel Veillard971771e2005-07-09 17:32:57 +000024234 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024235 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24236 (ctxt->user_sax->elementDecl != NULL))
24237 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24238}
24239
24240static void
24241notationDeclSplit(void *ctx, const xmlChar *name,
24242 const xmlChar *publicId, const xmlChar *systemId)
24243{
Daniel Veillard971771e2005-07-09 17:32:57 +000024244 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024245 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24246 (ctxt->user_sax->notationDecl != NULL))
24247 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24248 systemId);
24249}
24250
24251static void
24252unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24253 const xmlChar *publicId, const xmlChar *systemId,
24254 const xmlChar *notationName)
24255{
Daniel Veillard971771e2005-07-09 17:32:57 +000024256 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024257 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24258 (ctxt->user_sax->unparsedEntityDecl != NULL))
24259 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24260 systemId, notationName);
24261}
24262
24263static void
24264setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24265{
Daniel Veillard971771e2005-07-09 17:32:57 +000024266 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024267 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24268 (ctxt->user_sax->setDocumentLocator != NULL))
24269 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24270}
24271
24272static void
24273startDocumentSplit(void *ctx)
24274{
Daniel Veillard971771e2005-07-09 17:32:57 +000024275 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024276 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24277 (ctxt->user_sax->startDocument != NULL))
24278 ctxt->user_sax->startDocument(ctxt->user_data);
24279}
24280
24281static void
24282endDocumentSplit(void *ctx)
24283{
Daniel Veillard971771e2005-07-09 17:32:57 +000024284 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024285 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24286 (ctxt->user_sax->endDocument != NULL))
24287 ctxt->user_sax->endDocument(ctxt->user_data);
24288}
24289
24290static void
24291processingInstructionSplit(void *ctx, const xmlChar *target,
24292 const xmlChar *data)
24293{
Daniel Veillard971771e2005-07-09 17:32:57 +000024294 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024295 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24296 (ctxt->user_sax->processingInstruction != NULL))
24297 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24298}
24299
24300static void
24301commentSplit(void *ctx, const xmlChar *value)
24302{
Daniel Veillard971771e2005-07-09 17:32:57 +000024303 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024304 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24305 (ctxt->user_sax->comment != NULL))
24306 ctxt->user_sax->comment(ctxt->user_data, value);
24307}
24308
24309/*
24310 * Varargs error callbacks to the user application, harder ...
24311 */
24312
24313static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024314warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024315 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024316 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24317 (ctxt->user_sax->warning != NULL)) {
24318 TODO
24319 }
24320}
24321static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024322errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024323 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024324 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24325 (ctxt->user_sax->error != NULL)) {
24326 TODO
24327 }
24328}
24329static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024330fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024331 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024332 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24333 (ctxt->user_sax->fatalError != NULL)) {
24334 TODO
24335 }
24336}
24337
24338/*
24339 * Those are function where both the user handler and the schemas handler
24340 * need to be called.
24341 */
24342static void
24343charactersSplit(void *ctx, const xmlChar *ch, int len)
24344{
Daniel Veillard971771e2005-07-09 17:32:57 +000024345 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024346 if (ctxt == NULL)
24347 return;
24348 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24349 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24350 if (ctxt->ctxt != NULL)
24351 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24352}
24353
24354static void
24355ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24356{
Daniel Veillard971771e2005-07-09 17:32:57 +000024357 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024358 if (ctxt == NULL)
24359 return;
24360 if ((ctxt->user_sax != NULL) &&
24361 (ctxt->user_sax->ignorableWhitespace != NULL))
24362 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24363 if (ctxt->ctxt != NULL)
24364 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24365}
24366
24367static void
24368cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24369{
Daniel Veillard971771e2005-07-09 17:32:57 +000024370 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024371 if (ctxt == NULL)
24372 return;
24373 if ((ctxt->user_sax != NULL) &&
24374 (ctxt->user_sax->ignorableWhitespace != NULL))
24375 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24376 if (ctxt->ctxt != NULL)
24377 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24378}
24379
24380static void
24381referenceSplit(void *ctx, const xmlChar *name)
24382{
Daniel Veillard971771e2005-07-09 17:32:57 +000024383 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024384 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24385 (ctxt->user_sax->reference != NULL))
24386 ctxt->user_sax->reference(ctxt->user_data, name);
24387 if (ctxt->ctxt != NULL)
24388 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24389}
24390
24391static void
24392startElementNsSplit(void *ctx, const xmlChar * localname,
24393 const xmlChar * prefix, const xmlChar * URI,
24394 int nb_namespaces, const xmlChar ** namespaces,
24395 int nb_attributes, int nb_defaulted,
24396 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024397 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024398 if (ctxt == NULL)
24399 return;
24400 if ((ctxt->user_sax != NULL) &&
24401 (ctxt->user_sax->startElementNs != NULL))
24402 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24403 URI, nb_namespaces, namespaces,
24404 nb_attributes, nb_defaulted,
24405 attributes);
24406 if (ctxt->ctxt != NULL)
24407 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24408 URI, nb_namespaces, namespaces,
24409 nb_attributes, nb_defaulted,
24410 attributes);
24411}
24412
24413static void
24414endElementNsSplit(void *ctx, const xmlChar * localname,
24415 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024416 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024417 if (ctxt == NULL)
24418 return;
24419 if ((ctxt->user_sax != NULL) &&
24420 (ctxt->user_sax->endElementNs != NULL))
24421 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24422 if (ctxt->ctxt != NULL)
24423 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24424}
24425
Daniel Veillard4255d502002-04-16 15:50:10 +000024426/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024427 * xmlSchemaSAXPlug:
24428 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024429 * @sax: a pointer to the original xmlSAXHandlerPtr
24430 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024431 *
24432 * Plug a SAX based validation layer in a SAX parsing event flow.
24433 * The original @saxptr and @dataptr data are replaced by new pointers
24434 * but the calls to the original will be maintained.
24435 *
24436 * Returns a pointer to a data structure needed to unplug the validation layer
24437 * or NULL in case of errors.
24438 */
24439xmlSchemaSAXPlugPtr
24440xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24441 xmlSAXHandlerPtr *sax, void **user_data)
24442{
24443 xmlSchemaSAXPlugPtr ret;
24444 xmlSAXHandlerPtr old_sax;
24445
24446 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24447 return(NULL);
24448
24449 /*
24450 * We only allow to plug into SAX2 event streams
24451 */
24452 old_sax = *sax;
24453 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24454 return(NULL);
24455 if ((old_sax != NULL) &&
24456 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24457 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24458 return(NULL);
24459
24460 /*
24461 * everything seems right allocate the local data needed for that layer
24462 */
24463 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24464 if (ret == NULL) {
24465 return(NULL);
24466 }
24467 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24468 ret->magic = XML_SAX_PLUG_MAGIC;
24469 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24470 ret->ctxt = ctxt;
24471 ret->user_sax_ptr = sax;
24472 ret->user_sax = old_sax;
24473 if (old_sax == NULL) {
24474 /*
24475 * go direct, no need for the split block and functions.
24476 */
24477 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24478 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24479 /*
24480 * Note that we use the same text-function for both, to prevent
24481 * the parser from testing for ignorable whitespace.
24482 */
24483 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24484 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24485
24486 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24487 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24488
24489 ret->user_data = ctxt;
24490 *user_data = ctxt;
24491 } else {
24492 /*
24493 * for each callback unused by Schemas initialize it to the Split
24494 * routine only if non NULL in the user block, this can speed up
24495 * things at the SAX level.
24496 */
24497 if (old_sax->internalSubset != NULL)
24498 ret->schemas_sax.internalSubset = internalSubsetSplit;
24499 if (old_sax->isStandalone != NULL)
24500 ret->schemas_sax.isStandalone = isStandaloneSplit;
24501 if (old_sax->hasInternalSubset != NULL)
24502 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24503 if (old_sax->hasExternalSubset != NULL)
24504 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24505 if (old_sax->resolveEntity != NULL)
24506 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24507 if (old_sax->getEntity != NULL)
24508 ret->schemas_sax.getEntity = getEntitySplit;
24509 if (old_sax->entityDecl != NULL)
24510 ret->schemas_sax.entityDecl = entityDeclSplit;
24511 if (old_sax->notationDecl != NULL)
24512 ret->schemas_sax.notationDecl = notationDeclSplit;
24513 if (old_sax->attributeDecl != NULL)
24514 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24515 if (old_sax->elementDecl != NULL)
24516 ret->schemas_sax.elementDecl = elementDeclSplit;
24517 if (old_sax->unparsedEntityDecl != NULL)
24518 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24519 if (old_sax->setDocumentLocator != NULL)
24520 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24521 if (old_sax->startDocument != NULL)
24522 ret->schemas_sax.startDocument = startDocumentSplit;
24523 if (old_sax->endDocument != NULL)
24524 ret->schemas_sax.endDocument = endDocumentSplit;
24525 if (old_sax->processingInstruction != NULL)
24526 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24527 if (old_sax->comment != NULL)
24528 ret->schemas_sax.comment = commentSplit;
24529 if (old_sax->warning != NULL)
24530 ret->schemas_sax.warning = warningSplit;
24531 if (old_sax->error != NULL)
24532 ret->schemas_sax.error = errorSplit;
24533 if (old_sax->fatalError != NULL)
24534 ret->schemas_sax.fatalError = fatalErrorSplit;
24535 if (old_sax->getParameterEntity != NULL)
24536 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24537 if (old_sax->externalSubset != NULL)
24538 ret->schemas_sax.externalSubset = externalSubsetSplit;
24539
24540 /*
24541 * the 6 schemas callback have to go to the splitter functions
24542 * Note that we use the same text-function for ignorableWhitespace
24543 * if possible, to prevent the parser from testing for ignorable
24544 * whitespace.
24545 */
24546 ret->schemas_sax.characters = charactersSplit;
24547 if ((old_sax->ignorableWhitespace != NULL) &&
24548 (old_sax->ignorableWhitespace != old_sax->characters))
24549 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24550 else
24551 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24552 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24553 ret->schemas_sax.reference = referenceSplit;
24554 ret->schemas_sax.startElementNs = startElementNsSplit;
24555 ret->schemas_sax.endElementNs = endElementNsSplit;
24556
24557 ret->user_data_ptr = user_data;
24558 ret->user_data = *user_data;
24559 *user_data = ret;
24560 }
24561
24562 /*
24563 * plug the pointers back.
24564 */
24565 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024566 ctxt->sax = *sax;
24567 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24568 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024569 return(ret);
24570}
24571
24572/**
24573 * xmlSchemaSAXUnplug:
24574 * @plug: a data structure returned by xmlSchemaSAXPlug
24575 *
24576 * Unplug a SAX based validation layer in a SAX parsing event flow.
24577 * The original pointers used in the call are restored.
24578 *
24579 * Returns 0 in case of success and -1 in case of failure.
24580 */
24581int
24582xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24583{
24584 xmlSAXHandlerPtr *sax;
24585 void **user_data;
24586
24587 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24588 return(-1);
24589 plug->magic = 0;
24590
Daniel Veillardf10ae122005-07-10 19:03:16 +000024591 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024592 /* restore the data */
24593 sax = plug->user_sax_ptr;
24594 *sax = plug->user_sax;
24595 if (plug->user_sax != NULL) {
24596 user_data = plug->user_data_ptr;
24597 *user_data = plug->user_data;
24598 }
24599
24600 /* free and return */
24601 xmlFree(plug);
24602 return(0);
24603}
24604
24605/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024606 * xmlSchemaValidateStream:
24607 * @ctxt: a schema validation context
24608 * @input: the input to use for reading the data
24609 * @enc: an optional encoding information
24610 * @sax: a SAX handler for the resulting events
24611 * @user_data: the context to provide to the SAX handler.
24612 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024613 * Validate an input based on a flow of SAX event from the parser
24614 * and forward the events to the @sax handler with the provided @user_data
24615 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024616 *
24617 * Returns 0 if the document is schemas valid, a positive error code
24618 * number otherwise and -1 in case of internal or API error.
24619 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024620int
Daniel Veillard4255d502002-04-16 15:50:10 +000024621xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024622 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24623 xmlSAXHandlerPtr sax, void *user_data)
24624{
Daniel Veillard971771e2005-07-09 17:32:57 +000024625 xmlSchemaSAXPlugPtr plug = NULL;
24626 xmlSAXHandlerPtr old_sax = NULL;
24627 xmlParserCtxtPtr pctxt = NULL;
24628 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024629 int ret;
24630
Daniel Veillard4255d502002-04-16 15:50:10 +000024631 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024632 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024633
Daniel Veillardcdc82732005-07-08 15:04:06 +000024634 /*
24635 * prepare the parser
24636 */
24637 pctxt = xmlNewParserCtxt();
24638 if (pctxt == NULL)
24639 return (-1);
24640 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000024641 pctxt->sax = sax;
24642 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024643#if 0
24644 if (options)
24645 xmlCtxtUseOptions(pctxt, options);
24646#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024647 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024648
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024649 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024650 if (inputStream == NULL) {
24651 ret = -1;
24652 goto done;
24653 }
24654 inputPush(pctxt, inputStream);
24655 ctxt->parserCtxt = pctxt;
24656 ctxt->input = input;
24657
24658 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000024659 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000024660 */
Daniel Veillard971771e2005-07-09 17:32:57 +000024661 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
24662 if (plug == NULL) {
24663 ret = -1;
24664 goto done;
24665 }
24666 ctxt->input = input;
24667 ctxt->enc = enc;
24668 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024669 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24670 ret = xmlSchemaVStart(ctxt);
24671
24672 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24673 ret = ctxt->parserCtxt->errNo;
24674 if (ret == 0)
24675 ret = 1;
24676 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024677
24678done:
Daniel Veillard971771e2005-07-09 17:32:57 +000024679 ctxt->parserCtxt = NULL;
24680 ctxt->sax = NULL;
24681 ctxt->input = NULL;
24682 if (plug != NULL) {
24683 xmlSchemaSAXUnplug(plug);
24684 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024685 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000024686 if (pctxt != NULL) {
24687 pctxt->sax = old_sax;
24688 xmlFreeParserCtxt(pctxt);
24689 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024690 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024691}
24692
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024693/**
24694 * xmlSchemaValidateFile:
24695 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024696 * @filename: the URI of the instance
24697 * @options: a future set of options, currently unused
24698 *
24699 * Do a schemas validation of the given resource, it will use the
24700 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024701 *
24702 * Returns 0 if the document is valid, a positive error code
24703 * number otherwise and -1 in case of an internal or API error.
24704 */
24705int
24706xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024707 const char * filename,
24708 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024709{
Daniel Veillard81562d22005-06-15 13:27:56 +000024710#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024711 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024712 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024713
24714 if ((ctxt == NULL) || (filename == NULL))
24715 return (-1);
24716
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024717 input = xmlParserInputBufferCreateFilename(filename,
24718 XML_CHAR_ENCODING_NONE);
24719 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024720 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024721 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24722 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024723 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024724#else
24725 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024726#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024727}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024728
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024729#define bottom_xmlschemas
24730#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024731#endif /* LIBXML_SCHEMAS_ENABLED */