blob: 05ed65e6f08f8321b013dfa560e1d5fd58d94dbf [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000069#define DUMP_CONTENT_MODEL
70
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000071#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000104 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000105static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000107#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000108static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000109 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000110#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111
Daniel Veillard4255d502002-04-16 15:50:10 +0000112#define IS_SCHEMA(node, type) \
113 ((node != NULL) && (node->ns != NULL) && \
114 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
115 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
116
Daniel Veillardc0826a72004-08-10 14:17:33 +0000117#define FREE_AND_NULL(str) \
118 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000119 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120 str = NULL; \
121 }
122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000123#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000124 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
125 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000126
127#define IS_COMPLEX_TYPE(item) \
128 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
129 (item->builtInType == XML_SCHEMAS_ANYTYPE))
130
131#define IS_SIMPLE_TYPE(item) \
132 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
133 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000134 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000136#define IS_ANY_SIMPLE_TYPE(item) \
137 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000138 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000139
140#define IS_NOT_TYPEFIXED(item) \
141 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
142 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
143
144#define HAS_COMPLEX_CONTENT(item) \
145 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
146 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
147 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
148
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000149#define HAS_SIMPLE_CONTENT(item) \
150 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
151 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
152
153#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
154
155#define IS_PARTICLE_EMPTIABLE(item) \
156 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000158#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000160#define GET_LIST_ITEM_TYPE(item) item->subtypes
161
162#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
163#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
164#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000166#define IS_MODEL_GROUP(item) \
167 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
168 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
169 (item->type == XML_SCHEMA_TYPE_ALL))
170
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000171#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
172
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000173#define ELEM_TYPE(item) item->subtypes
174
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000175#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000177#define SUBST_GROUP_AFF(item) item->refDecl
178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000179#if 0
180#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
181#endif
182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000183#define SUBSET_RESTRICTION 1<<0
184#define SUBSET_EXTENSION 1<<1
185#define SUBSET_SUBSTITUTION 1<<2
186#define SUBSET_LIST 1<<3
187#define SUBSET_UNION 1<<4
188
Daniel Veillard4255d502002-04-16 15:50:10 +0000189#define XML_SCHEMAS_PARSE_ERROR 1
190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000193typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
194typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000199
200typedef struct _xmlSchemaItemList xmlSchemaItemList;
201typedef xmlSchemaItemList *xmlSchemaItemListPtr;
202
203struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000204 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 int nbItems; /* used for dynamic addition of schemata */
206 int sizeItems; /* used for dynamic addition of schemata */
207};
208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000209typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
210typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
211struct _xmlSchemaAbstractCtxt {
212 int type;
213};
214
215#define XML_SCHEMA_CTXT_PARSER 1
216#define XML_SCHEMA_CTXT_VALIDATOR 2
217
Daniel Veillard4255d502002-04-16 15:50:10 +0000218struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000219 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 void *userData; /* user specific data block */
221 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
222 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000223 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000227 xmlSchemaPtr topschema; /* The main schema */
228 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000231 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 int counter;
233
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000234 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000236 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 const char *buffer;
239 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241 /*
242 * Used to build complex element content models
243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245 xmlAutomataStatePtr start;
246 xmlAutomataStatePtr end;
247 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000248
249 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000250 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000251 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
252 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 xmlSchemaAssemblePtr assemble;
254 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000256 const xmlChar **localImports; /* list of locally imported namespaces */
257 int sizeLocalImports;
258 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000259 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000260 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000261};
262
Daniel Veillard4255d502002-04-16 15:50:10 +0000263#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000267#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
269#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000270#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000271#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
273#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
274#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
275#define XML_SCHEMAS_ATTR_WILD_SKIP 13
276#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
277#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
278#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
279#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281/**
282 * xmlSchemaBasicItem:
283 *
284 * The abstract base type for schema components.
285 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000286typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
287typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
288struct _xmlSchemaBasicItem {
289 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000290};
291
292/**
293 * xmlSchemaAnnotItem:
294 *
295 * The abstract base type for annotated schema components.
296 * (Extends xmlSchemaBasicItem)
297 */
298typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
299typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
300struct _xmlSchemaAnnotItem {
301 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000302 xmlSchemaAnnotPtr annot;
303};
304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000305/**
306 * xmlSchemaTreeItem:
307 *
308 * The abstract base type for tree-like structured schema components.
309 * (Extends xmlSchemaAnnotItem)
310 */
311typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
312typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
313struct _xmlSchemaTreeItem {
314 xmlSchemaTypeType type;
315 xmlSchemaAnnotPtr annot;
316 xmlSchemaTreeItemPtr next;
317 xmlSchemaTreeItemPtr children;
318};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000320/**
321 * xmlSchemaQNameRef:
322 *
323 * A component reference item (not a schema component)
324 * (Extends xmlSchemaBasicItem)
325 */
326typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
327typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
328struct _xmlSchemaQNameRef {
329 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000331 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000332 const xmlChar *name;
333 const xmlChar *targetNamespace;
334};
335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000336/**
337 * xmlSchemaParticle:
338 *
339 * A particle component.
340 * (Extends xmlSchemaTreeItem)
341 */
342typedef struct _xmlSchemaParticle xmlSchemaParticle;
343typedef xmlSchemaParticle *xmlSchemaParticlePtr;
344struct _xmlSchemaParticle {
345 xmlSchemaTypeType type;
346 xmlSchemaAnnotPtr annot;
347 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
348 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
349 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000350 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351 xmlNodePtr node;
352};
353
354/**
355 * xmlSchemaModelGroup:
356 *
357 * A model group component.
358 * (Extends xmlSchemaTreeItem)
359 */
360typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next; /* not used */
366 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
367 xmlNodePtr node;
368};
369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000370#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000371/**
372 * xmlSchemaModelGroupDef:
373 *
374 * A model group definition component.
375 * (Extends xmlSchemaTreeItem)
376 */
377typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
378typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
379struct _xmlSchemaModelGroupDef {
380 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
381 xmlSchemaAnnotPtr annot;
382 xmlSchemaTreeItemPtr next; /* not used */
383 xmlSchemaTreeItemPtr children; /* the "model group" */
384 const xmlChar *name;
385 const xmlChar *targetNamespace;
386 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000387 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388};
389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390typedef struct _xmlSchemaIDC xmlSchemaIDC;
391typedef xmlSchemaIDC *xmlSchemaIDCPtr;
392
393/**
394 * xmlSchemaIDCSelect:
395 *
396 * The identity-constraint "field" and "selector" item, holding the
397 * XPath expression.
398 */
399typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
400typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000401struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402 xmlSchemaIDCSelectPtr next;
403 xmlSchemaIDCPtr idc;
404 int index; /* an index position if significant for IDC key-sequences */
405 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000406 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000407};
408
409/**
410 * xmlSchemaIDC:
411 *
412 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000413 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000414 */
415
416struct _xmlSchemaIDC {
417 xmlSchemaTypeType type;
418 xmlSchemaAnnotPtr annot;
419 xmlSchemaIDCPtr next;
420 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 const xmlChar *targetNamespace;
423 xmlSchemaIDCSelectPtr selector;
424 xmlSchemaIDCSelectPtr fields;
425 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000426 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000427};
428
429/**
430 * xmlSchemaIDCAug:
431 *
432 * The augmented IDC information used for validation.
433 */
434typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
435typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
436struct _xmlSchemaIDCAug {
437 xmlSchemaIDCAugPtr next; /* next in a list */
438 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000439 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000440 tables need to be bubbled upwards */
441};
442
443/**
444 * xmlSchemaPSVIIDCKeySequence:
445 *
446 * The key sequence of a node table item.
447 */
448typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
449typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
450struct _xmlSchemaPSVIIDCKey {
451 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000452 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453};
454
455/**
456 * xmlSchemaPSVIIDCNode:
457 *
458 * The node table item of a node table.
459 */
460typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
461typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
462struct _xmlSchemaPSVIIDCNode {
463 xmlNodePtr node;
464 xmlSchemaPSVIIDCKeyPtr *keys;
465};
466
467/**
468 * xmlSchemaPSVIIDCBinding:
469 *
470 * The identity-constraint binding item of the [identity-constraint table].
471 */
472typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
473typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
474struct _xmlSchemaPSVIIDCBinding {
475 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
476 xmlSchemaIDCPtr definition; /* the IDC definition */
477 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
478 int nbNodes; /* number of entries in the node table */
479 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000480 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 table */
482 /* int nbKeys; number of keys in each key-sequence */
483};
484
485#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
486#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
487
488#define XPATH_STATE_OBJ_MATCHES -2
489#define XPATH_STATE_OBJ_BLOCKED -3
490
491typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
492typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
493
494/**
495 * xmlSchemaIDCStateObj:
496 *
497 * The state object used to evaluate XPath expressions.
498 */
499typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
500typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
501struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000502 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000504 int depth; /* depth of creation */
505 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 int nbHistory;
507 int sizeHistory;
508 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
509 matcher */
510 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000511 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000512};
513
514#define IDC_MATCHER 0
515
516/**
517 * xmlSchemaIDCMatcher:
518 *
519 * Used to IDC selectors (and fields) successively.
520 */
521struct _xmlSchemaIDCMatcher {
522 int type;
523 int depth; /* the tree depth at creation time */
524 xmlSchemaIDCMatcherPtr next; /* next in the list */
525 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
526 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
527 elements */
528 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 int targetDepth;
530};
531
532/*
533* Element info flags.
534*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
536#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
537#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
538#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
539
540#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
541#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
542#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
543
544#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
545#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
546#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
547#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548
549/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000550 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 *
552 * Holds information of an element node.
553 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000554struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000557 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 const xmlChar *nsName;
559 const xmlChar *value;
560 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000562 int flags; /* combination of node info flags */
563 int valNeeded;
564 int normVal;
565
566 xmlSchemaElementPtr decl; /* the element/attribute declaration */
567 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
569 for the scope element*/
570 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
571 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000572 xmlRegExecCtxtPtr regexCtxt;
573
574 const xmlChar **nsBindings; /* Namespace bindings on this element */
575 int nbNsBindings;
576 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000577};
578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000579/*
580* @metaType values of xmlSchemaAttrInfo.
581*/
582#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
584#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
585#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
586#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
589typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
590struct _xmlSchemaAttrInfo {
591 xmlNodePtr node;
592 int nodeType;
593 const xmlChar *localName;
594 const xmlChar *nsName;
595 const xmlChar *value;
596 xmlSchemaValPtr val; /* the pre-computed value if any */
597 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
598 int flags; /* combination of node info flags */
599
600 xmlSchemaAttributePtr decl; /* the attribute declaration */
601 xmlSchemaAttributePtr use; /* the attribute use */
602 int state;
603 int metaType;
604 const xmlChar *vcValue; /* the value constraint value */
605 xmlSchemaNodeInfoPtr parent;
606};
607
608
609#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000610/**
611 * xmlSchemaValidCtxt:
612 *
613 * A Schemas validation context
614 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000615struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *userData; /* user specific data block */
618 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000619 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000621
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 xmlSchemaPtr schema; /* The schema in use */
623 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 xmlCharEncoding enc;
626 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000627 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000629
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 int err;
631 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000632
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000633 xmlNodePtr node;
634 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000635 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637 xmlRegExecCtxtPtr regexp;
638 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000639
Daniel Veillardc0826a72004-08-10 14:17:33 +0000640 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000641 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000642 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000643 xmlSchemaParserCtxtPtr pctxt;
644 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000647 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000649 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
652
653 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
654 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000655
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
657 int nbIdcNodes;
658 int sizeIdcNodes;
659
660 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
661 int nbIdcKeys;
662 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000663
664 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000665
666 xmlDictPtr dict;
667
Daniel Veillard39e5c892005-07-03 22:48:50 +0000668#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000670#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671
672 xmlSchemaAttrInfoPtr *attrInfos;
673 int nbAttrInfos;
674 int sizeAttrInfos;
675
676 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000677};
678
Daniel Veillard1d913862003-11-21 00:28:39 +0000679/*
680 * These are the entries in the schemas importSchemas hash table
681 */
682typedef struct _xmlSchemaImport xmlSchemaImport;
683typedef xmlSchemaImport *xmlSchemaImportPtr;
684struct _xmlSchemaImport {
685 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000686 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000687 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000688 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000689};
Daniel Veillard4255d502002-04-16 15:50:10 +0000690
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000691/*
692 * These are the entries associated to includes in a schemas
693 */
694typedef struct _xmlSchemaInclude xmlSchemaInclude;
695typedef xmlSchemaInclude *xmlSchemaIncludePtr;
696struct _xmlSchemaInclude {
697 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698 const xmlChar *schemaLocation;
699 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000700 const xmlChar *origTargetNamespace;
701 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000702};
703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000704/**
705 * xmlSchemaSubstGroup:
706 *
707 *
708 */
709typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
710typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
711struct _xmlSchemaSubstGroup {
712 xmlSchemaElementPtr head;
713 xmlSchemaItemListPtr members;
714};
715
Daniel Veillard4255d502002-04-16 15:50:10 +0000716/************************************************************************
717 * *
718 * Some predeclarations *
719 * *
720 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000722static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
723 xmlSchemaPtr schema,
724 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725static void
726xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
727 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000728static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000729xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
730static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000731xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
732 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000733static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000734xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
735 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000736static void
737xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000738static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000739xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740static xmlSchemaTreeItemPtr
741xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
742 xmlNodePtr node, xmlSchemaTypeType type,
743 int withParticle);
744static const xmlChar *
745xmlSchemaCompTypeToString(xmlSchemaTypeType type);
746static xmlSchemaTypeLinkPtr
747xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748static void
749xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
750 const char *funcName,
751 const char *message);
752static int
753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
754 xmlSchemaTypePtr baseType,
755 int subset);
756static void
757xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
758 xmlSchemaParserCtxtPtr ctxt,
759 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000760
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761/************************************************************************
762 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000763 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 * *
765 ************************************************************************/
766
767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000768 * xmlSchemaCompTypeToString:
769 * @type: the type of the schema item
770 *
771 * Returns the component name of a schema item.
772 */
773static const xmlChar *
774xmlSchemaCompTypeToString(xmlSchemaTypeType type)
775{
776 switch (type) {
777 case XML_SCHEMA_TYPE_SIMPLE:
778 return(BAD_CAST "simple type definition");
779 case XML_SCHEMA_TYPE_COMPLEX:
780 return(BAD_CAST "complex type definition");
781 case XML_SCHEMA_TYPE_ELEMENT:
782 return(BAD_CAST "element declaration");
783 case XML_SCHEMA_TYPE_ATTRIBUTE:
784 return(BAD_CAST "attribute declaration");
785 case XML_SCHEMA_TYPE_GROUP:
786 return(BAD_CAST "model group definition");
787 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
788 return(BAD_CAST "attribute group definition");
789 case XML_SCHEMA_TYPE_NOTATION:
790 return(BAD_CAST "notation declaration");
791 case XML_SCHEMA_TYPE_SEQUENCE:
792 return(BAD_CAST "model group (sequence)");
793 case XML_SCHEMA_TYPE_CHOICE:
794 return(BAD_CAST "model group (choice)");
795 case XML_SCHEMA_TYPE_ALL:
796 return(BAD_CAST "model group (all)");
797 case XML_SCHEMA_TYPE_PARTICLE:
798 return(BAD_CAST "particle");
799 default:
800 return(BAD_CAST "Not a schema component");
801 }
802}
803
804/**
805 * xmlSchemaGetComponentNode:
806 * @item: a schema component
807 *
808 * Returns node associated with the schema component.
809 * NOTE that such a node need not be available; plus, a component's
810 * node need not to reflect the component directly, since there is no
811 * one-to-one relationship between the XML Schema representation and
812 * the component representation.
813 */
814static xmlNodePtr
815xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
816{
817 switch (item->type) {
818 case XML_SCHEMA_TYPE_ELEMENT:
819 return (((xmlSchemaElementPtr) item)->node);
820 case XML_SCHEMA_TYPE_ATTRIBUTE:
821 return (((xmlSchemaAttributePtr) item)->node);
822 case XML_SCHEMA_TYPE_COMPLEX:
823 case XML_SCHEMA_TYPE_SIMPLE:
824 return (((xmlSchemaTypePtr) item)->node);
825 case XML_SCHEMA_TYPE_ANY:
826 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
827 return (((xmlSchemaWildcardPtr) item)->node);
828 case XML_SCHEMA_TYPE_PARTICLE:
829 return (((xmlSchemaParticlePtr) item)->node);
830 case XML_SCHEMA_TYPE_SEQUENCE:
831 case XML_SCHEMA_TYPE_CHOICE:
832 case XML_SCHEMA_TYPE_ALL:
833 return (((xmlSchemaModelGroupPtr) item)->node);
834 case XML_SCHEMA_TYPE_GROUP:
835 return (((xmlSchemaModelGroupDefPtr) item)->node);
836 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
837 return (((xmlSchemaAttributeGroupPtr) item)->node);
838 case XML_SCHEMA_TYPE_IDC_UNIQUE:
839 case XML_SCHEMA_TYPE_IDC_KEY:
840 case XML_SCHEMA_TYPE_IDC_KEYREF:
841 return (((xmlSchemaIDCPtr) item)->node);
842 default:
843 return (NULL);
844 }
845}
846
847#if 0
848/**
849 * xmlSchemaGetNextComponent:
850 * @item: a schema component
851 *
852 * Returns the next sibling of the schema component.
853 */
854static xmlSchemaBasicItemPtr
855xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
856{
857 switch (item->type) {
858 case XML_SCHEMA_TYPE_ELEMENT:
859 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
860 case XML_SCHEMA_TYPE_ATTRIBUTE:
861 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
862 case XML_SCHEMA_TYPE_COMPLEX:
863 case XML_SCHEMA_TYPE_SIMPLE:
864 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
865 case XML_SCHEMA_TYPE_ANY:
866 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
867 return (NULL);
868 case XML_SCHEMA_TYPE_PARTICLE:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
870 case XML_SCHEMA_TYPE_SEQUENCE:
871 case XML_SCHEMA_TYPE_CHOICE:
872 case XML_SCHEMA_TYPE_ALL:
873 return (NULL);
874 case XML_SCHEMA_TYPE_GROUP:
875 return (NULL);
876 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
877 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
878 case XML_SCHEMA_TYPE_IDC_UNIQUE:
879 case XML_SCHEMA_TYPE_IDC_KEY:
880 case XML_SCHEMA_TYPE_IDC_KEYREF:
881 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
882 default:
883 return (NULL);
884 }
885}
886#endif
887
888/**
889 * xmlSchemaGetAttrName:
890 * @attr: the attribute declaration/use
891 *
892 * Returns the name of the attribute; if the attribute
893 * is a reference, the name of the referenced global type will be returned.
894 */
895static const xmlChar *
896xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
897{
898 if (attr->ref != NULL)
899 return(attr->ref);
900 else
901 return(attr->name);
902}
903
904/**
905 * xmlSchemaGetAttrTargetNsURI:
906 * @type: the type (element or attribute)
907 *
908 * Returns the target namespace URI of the type; if the type is a reference,
909 * the target namespace of the referenced type will be returned.
910 */
911static const xmlChar *
912xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
913{
914 if (attr->ref != NULL)
915 return (attr->refNs);
916 else
917 return(attr->targetNamespace);
918}
919
920/**
921 * xmlSchemaFormatQName:
922 * @buf: the string buffer
923 * @namespaceName: the namespace name
924 * @localName: the local name
925 *
926 * Returns the given QName in the format "{namespaceName}localName" or
927 * just "localName" if @namespaceName is NULL.
928 *
929 * Returns the localName if @namespaceName is NULL, a formatted
930 * string otherwise.
931 */
932static const xmlChar*
933xmlSchemaFormatQName(xmlChar **buf,
934 const xmlChar *namespaceName,
935 const xmlChar *localName)
936{
937 FREE_AND_NULL(*buf)
938 if (namespaceName == NULL)
939 return(localName);
940
941 *buf = xmlStrdup(BAD_CAST "{");
942 *buf = xmlStrcat(*buf, namespaceName);
943 *buf = xmlStrcat(*buf, BAD_CAST "}");
944 *buf = xmlStrcat(*buf, localName);
945
946 return ((const xmlChar *) *buf);
947}
948
949static const xmlChar*
950xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
951{
952 if (ns != NULL)
953 return (xmlSchemaFormatQName(buf, ns->href, localName));
954 else
955 return (xmlSchemaFormatQName(buf, NULL, localName));
956}
957
958static const xmlChar *
959xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
960{
961 switch (item->type) {
962 case XML_SCHEMA_TYPE_ELEMENT:
963 return (((xmlSchemaElementPtr) item)->name);
964 case XML_SCHEMA_TYPE_ATTRIBUTE:
965 return (((xmlSchemaAttributePtr) item)->name);
966 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
967 return (((xmlSchemaAttributeGroupPtr) item)->name);
968 case XML_SCHEMA_TYPE_BASIC:
969 case XML_SCHEMA_TYPE_SIMPLE:
970 case XML_SCHEMA_TYPE_COMPLEX:
971 return (((xmlSchemaTypePtr) item)->name);
972 case XML_SCHEMA_TYPE_GROUP:
973 return (((xmlSchemaModelGroupDefPtr) item)->name);
974 case XML_SCHEMA_TYPE_IDC_KEY:
975 case XML_SCHEMA_TYPE_IDC_UNIQUE:
976 case XML_SCHEMA_TYPE_IDC_KEYREF:
977 return (((xmlSchemaIDCPtr) item)->name);
978 default:
979 /*
980 * Other components cannot have names.
981 */
982 break;
983 }
984 return (NULL);
985}
986
987static const xmlChar *
988xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
989{
990 switch (item->type) {
991 case XML_SCHEMA_TYPE_ELEMENT:
992 return (((xmlSchemaElementPtr) item)->targetNamespace);
993 case XML_SCHEMA_TYPE_ATTRIBUTE:
994 return (((xmlSchemaAttributePtr) item)->targetNamespace);
995 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
996 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
997 case XML_SCHEMA_TYPE_BASIC:
998 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
999 case XML_SCHEMA_TYPE_SIMPLE:
1000 case XML_SCHEMA_TYPE_COMPLEX:
1001 return (((xmlSchemaTypePtr) item)->targetNamespace);
1002 case XML_SCHEMA_TYPE_GROUP:
1003 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1004 case XML_SCHEMA_TYPE_IDC_KEY:
1005 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1006 case XML_SCHEMA_TYPE_IDC_KEYREF:
1007 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1008 default:
1009 /*
1010 * Other components cannot have names.
1011 */
1012 break;
1013 }
1014 return (NULL);
1015}
1016
1017static const xmlChar*
1018xmlSchemaGetComponentQName(xmlChar **buf,
1019 void *item)
1020{
1021 return (xmlSchemaFormatQName(buf,
1022 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1023 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1024}
1025
1026/**
1027 * xmlSchemaWildcardPCToString:
1028 * @pc: the type of processContents
1029 *
1030 * Returns a string representation of the type of
1031 * processContents.
1032 */
1033static const xmlChar *
1034xmlSchemaWildcardPCToString(int pc)
1035{
1036 switch (pc) {
1037 case XML_SCHEMAS_ANY_SKIP:
1038 return (BAD_CAST "skip");
1039 case XML_SCHEMAS_ANY_LAX:
1040 return (BAD_CAST "lax");
1041 case XML_SCHEMAS_ANY_STRICT:
1042 return (BAD_CAST "strict");
1043 default:
1044 return (BAD_CAST "invalid process contents");
1045 }
1046}
1047
1048/**
1049 * xmlSchemaGetCanonValueWhtspExt:
1050 * @val: the precomputed value
1051 * @retValue: the returned value
1052 * @ws: the whitespace type of the value
1053 *
1054 * Get a the cononical representation of the value.
1055 * The caller has to free the returned retValue.
1056 *
1057 * Returns 0 if the value could be built and -1 in case of
1058 * API errors or if the value type is not supported yet.
1059 */
1060static int
1061xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1062 xmlSchemaWhitespaceValueType ws,
1063 xmlChar **retValue)
1064{
1065 int list;
1066 xmlSchemaValType valType;
1067 const xmlChar *value, *value2 = NULL;
1068
1069
1070 if ((retValue == NULL) || (val == NULL))
1071 return (-1);
1072 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1073 *retValue = NULL;
1074 do {
1075 value = NULL;
1076 valType = xmlSchemaGetValType(val);
1077 switch (valType) {
1078 case XML_SCHEMAS_STRING:
1079 case XML_SCHEMAS_NORMSTRING:
1080 case XML_SCHEMAS_ANYSIMPLETYPE:
1081 value = xmlSchemaValueGetAsString(val);
1082 if (value != NULL) {
1083 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1084 value2 = xmlSchemaCollapseString(value);
1085 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1086 value2 = xmlSchemaWhiteSpaceReplace(value);
1087 if (value2 != NULL)
1088 value = value2;
1089 }
1090 break;
1091 default:
1092 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1093 if (value2 != NULL)
1094 xmlFree((xmlChar *) value2);
1095 goto internal_error;
1096 }
1097 value = value2;
1098 }
1099 if (*retValue == NULL)
1100 if (value == NULL) {
1101 if (! list)
1102 *retValue = xmlStrdup(BAD_CAST "");
1103 } else
1104 *retValue = xmlStrdup(value);
1105 else if (value != NULL) {
1106 /* List. */
1107 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1108 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1109 }
1110 FREE_AND_NULL(value2)
1111 val = xmlSchemaValueGetNext(val);
1112 } while (val != NULL);
1113
1114 return (0);
1115internal_error:
1116 if (*retValue != NULL)
1117 xmlFree((xmlChar *) (*retValue));
1118 if (value2 != NULL)
1119 xmlFree((xmlChar *) value2);
1120 return (-1);
1121}
1122
1123/**
1124 * xmlSchemaFormatItemForReport:
1125 * @buf: the string buffer
1126 * @itemDes: the designation of the item
1127 * @itemName: the name of the item
1128 * @item: the item as an object
1129 * @itemNode: the node of the item
1130 * @local: the local name
1131 * @parsing: if the function is used during the parse
1132 *
1133 * Returns a representation of the given item used
1134 * for error reports.
1135 *
1136 * The following order is used to build the resulting
1137 * designation if the arguments are not NULL:
1138 * 1a. If itemDes not NULL -> itemDes
1139 * 1b. If (itemDes not NULL) and (itemName not NULL)
1140 * -> itemDes + itemName
1141 * 2. If the preceding was NULL and (item not NULL) -> item
1142 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1143 *
1144 * If the itemNode is an attribute node, the name of the attribute
1145 * will be appended to the result.
1146 *
1147 * Returns the formatted string and sets @buf to the resulting value.
1148 */
1149static xmlChar*
1150xmlSchemaFormatItemForReport(xmlChar **buf,
1151 const xmlChar *itemDes,
1152 xmlSchemaTypePtr item,
1153 xmlNodePtr itemNode)
1154{
1155 xmlChar *str = NULL;
1156 int named = 1;
1157
1158 if (*buf != NULL) {
1159 xmlFree(*buf);
1160 *buf = NULL;
1161 }
1162
1163 if (itemDes != NULL) {
1164 *buf = xmlStrdup(itemDes);
1165 } else if (item != NULL) {
1166 switch (item->type) {
1167 case XML_SCHEMA_TYPE_BASIC:
1168 if (VARIETY_ATOMIC(item))
1169 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1170 else if (VARIETY_LIST(item))
1171 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1172 else if (VARIETY_UNION(item))
1173 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1174 else
1175 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1176 *buf = xmlStrcat(*buf, item->name);
1177 *buf = xmlStrcat(*buf, BAD_CAST "'");
1178 break;
1179 case XML_SCHEMA_TYPE_SIMPLE:
1180 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1181 *buf = xmlStrdup(BAD_CAST"");
1182 } else {
1183 *buf = xmlStrdup(BAD_CAST "local ");
1184 }
1185 if (VARIETY_ATOMIC(item))
1186 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1187 else if (VARIETY_LIST(item))
1188 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1189 else if (VARIETY_UNION(item))
1190 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1191 else
1192 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1193 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1194 *buf = xmlStrcat(*buf, BAD_CAST " '");
1195 *buf = xmlStrcat(*buf, item->name);
1196 *buf = xmlStrcat(*buf, BAD_CAST "'");
1197 }
1198 break;
1199 case XML_SCHEMA_TYPE_COMPLEX:
1200 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1201 *buf = xmlStrdup(BAD_CAST "");
1202 else
1203 *buf = xmlStrdup(BAD_CAST "local ");
1204 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1205 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1206 *buf = xmlStrcat(*buf, BAD_CAST " '");
1207 *buf = xmlStrcat(*buf, item->name);
1208 *buf = xmlStrcat(*buf, BAD_CAST "'");
1209 }
1210 break;
1211 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1212 xmlSchemaAttributePtr attr;
1213
1214 attr = (xmlSchemaAttributePtr) item;
1215 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1216 (attr->ref == NULL)) {
1217 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1218 *buf = xmlStrcat(*buf, BAD_CAST " '");
1219 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1220 attr->targetNamespace, attr->name));
1221 FREE_AND_NULL(str)
1222 *buf = xmlStrcat(*buf, BAD_CAST "'");
1223 } else {
1224 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1225 *buf = xmlStrcat(*buf, BAD_CAST " '");
1226 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1227 attr->refNs, attr->ref));
1228 FREE_AND_NULL(str)
1229 *buf = xmlStrcat(*buf, BAD_CAST "'");
1230 }
1231 }
1232 break;
1233 case XML_SCHEMA_TYPE_ELEMENT: {
1234 xmlSchemaElementPtr elem;
1235
1236 elem = (xmlSchemaElementPtr) item;
1237 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1238 (elem->ref == NULL)) {
1239 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1240 *buf = xmlStrcat(*buf, BAD_CAST " '");
1241 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1242 elem->targetNamespace, elem->name));
1243 *buf = xmlStrcat(*buf, BAD_CAST "'");
1244 }
1245 }
1246 break;
1247 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1248 case XML_SCHEMA_TYPE_IDC_KEY:
1249 case XML_SCHEMA_TYPE_IDC_KEYREF:
1250 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1251 *buf = xmlStrdup(BAD_CAST "unique '");
1252 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1253 *buf = xmlStrdup(BAD_CAST "key '");
1254 else
1255 *buf = xmlStrdup(BAD_CAST "keyRef '");
1256 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1257 *buf = xmlStrcat(*buf, BAD_CAST "'");
1258 break;
1259 case XML_SCHEMA_TYPE_ANY:
1260 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1261 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1262 ((xmlSchemaWildcardPtr) item)->processContents));
1263 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1264 break;
1265 case XML_SCHEMA_FACET_MININCLUSIVE:
1266 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1267 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1268 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1269 case XML_SCHEMA_FACET_TOTALDIGITS:
1270 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1271 case XML_SCHEMA_FACET_PATTERN:
1272 case XML_SCHEMA_FACET_ENUMERATION:
1273 case XML_SCHEMA_FACET_WHITESPACE:
1274 case XML_SCHEMA_FACET_LENGTH:
1275 case XML_SCHEMA_FACET_MAXLENGTH:
1276 case XML_SCHEMA_FACET_MINLENGTH:
1277 *buf = xmlStrdup(BAD_CAST "facet '");
1278 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1279 *buf = xmlStrcat(*buf, BAD_CAST "'");
1280 break;
1281 case XML_SCHEMA_TYPE_NOTATION:
1282 *buf = xmlStrdup(BAD_CAST "notation");
1283 break;
1284 case XML_SCHEMA_TYPE_GROUP: {
1285 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1286 *buf = xmlStrcat(*buf, BAD_CAST " '");
1287 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1288 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1289 ((xmlSchemaModelGroupDefPtr) item)->name));
1290 *buf = xmlStrcat(*buf, BAD_CAST "'");
1291 FREE_AND_NULL(str)
1292 }
1293 break;
1294 case XML_SCHEMA_TYPE_SEQUENCE:
1295 case XML_SCHEMA_TYPE_CHOICE:
1296 case XML_SCHEMA_TYPE_ALL:
1297 case XML_SCHEMA_TYPE_PARTICLE:
1298 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1299 break;
1300 default:
1301 named = 0;
1302 }
1303 } else
1304 named = 0;
1305
1306 if ((named == 0) && (itemNode != NULL)) {
1307 xmlNodePtr elem;
1308
1309 if (itemNode->type == XML_ATTRIBUTE_NODE)
1310 elem = itemNode->parent;
1311 else
1312 elem = itemNode;
1313 *buf = xmlStrdup(BAD_CAST "Element '");
1314 if (elem->ns != NULL) {
1315 *buf = xmlStrcat(*buf,
1316 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1317 FREE_AND_NULL(str)
1318 } else
1319 *buf = xmlStrcat(*buf, elem->name);
1320 *buf = xmlStrcat(*buf, BAD_CAST "'");
1321
1322 }
1323 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1324 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1325 if (itemNode->ns != NULL) {
1326 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1327 itemNode->ns->href, itemNode->name));
1328 FREE_AND_NULL(str)
1329 } else
1330 *buf = xmlStrcat(*buf, itemNode->name);
1331 *buf = xmlStrcat(*buf, BAD_CAST "'");
1332 }
1333 FREE_AND_NULL(str)
1334
1335 return (*buf);
1336}
1337
1338/**
1339 * xmlSchemaFormatFacetEnumSet:
1340 * @buf: the string buffer
1341 * @type: the type holding the enumeration facets
1342 *
1343 * Builds a string consisting of all enumeration elements.
1344 *
1345 * Returns a string of all enumeration elements.
1346 */
1347static const xmlChar *
1348xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1349 xmlChar **buf, xmlSchemaTypePtr type)
1350{
1351 xmlSchemaFacetPtr facet;
1352 xmlSchemaWhitespaceValueType ws;
1353 xmlChar *value = NULL;
1354 int res;
1355
1356 if (*buf != NULL)
1357 xmlFree(*buf);
1358 *buf = NULL;
1359
1360 do {
1361 /*
1362 * Use the whitespace type of the base type.
1363 */
1364 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1365 for (facet = type->facets; facet != NULL; facet = facet->next) {
1366 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1367 continue;
1368 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1369 ws, &value);
1370 if (res == -1) {
1371 xmlSchemaInternalErr(actxt,
1372 "xmlSchemaFormatFacetEnumSet",
1373 "compute the canonical lexical representation");
1374 if (*buf != NULL)
1375 xmlFree(*buf);
1376 *buf = NULL;
1377 return (NULL);
1378 }
1379 if (*buf == NULL)
1380 *buf = xmlStrdup(BAD_CAST "'");
1381 else
1382 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1383 *buf = xmlStrcat(*buf, BAD_CAST value);
1384 *buf = xmlStrcat(*buf, BAD_CAST "'");
1385 if (value != NULL) {
1386 xmlFree((xmlChar *)value);
1387 value = NULL;
1388 }
1389 }
1390 type = type->baseType;
1391 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1392
1393 return ((const xmlChar *) *buf);
1394}
1395
1396/************************************************************************
1397 * *
1398 * Error functions *
1399 * *
1400 ************************************************************************/
1401
1402#if 0
1403static void
1404xmlSchemaErrMemory(const char *msg)
1405{
1406 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1407 msg);
1408}
1409#endif
1410
1411/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001412 * xmlSchemaPErrMemory:
1413 * @node: a context node
1414 * @extra: extra informations
1415 *
1416 * Handle an out of memory condition
1417 */
1418static void
1419xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1420 const char *extra, xmlNodePtr node)
1421{
1422 if (ctxt != NULL)
1423 ctxt->nberrors++;
1424 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1425 extra);
1426}
1427
1428/**
1429 * xmlSchemaPErr:
1430 * @ctxt: the parsing context
1431 * @node: the context node
1432 * @error: the error code
1433 * @msg: the error message
1434 * @str1: extra data
1435 * @str2: extra data
1436 *
1437 * Handle a parser error
1438 */
1439static void
1440xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1441 const char *msg, const xmlChar * str1, const xmlChar * str2)
1442{
1443 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001444 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001445 void *data = NULL;
1446
1447 if (ctxt != NULL) {
1448 ctxt->nberrors++;
1449 channel = ctxt->error;
1450 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001451 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001453 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 error, XML_ERR_ERROR, NULL, 0,
1455 (const char *) str1, (const char *) str2, NULL, 0, 0,
1456 msg, str1, str2);
1457}
1458
1459/**
1460 * xmlSchemaPErr2:
1461 * @ctxt: the parsing context
1462 * @node: the context node
1463 * @node: the current child
1464 * @error: the error code
1465 * @msg: the error message
1466 * @str1: extra data
1467 * @str2: extra data
1468 *
1469 * Handle a parser error
1470 */
1471static void
1472xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1473 xmlNodePtr child, int error,
1474 const char *msg, const xmlChar * str1, const xmlChar * str2)
1475{
1476 if (child != NULL)
1477 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1478 else
1479 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1480}
1481
Daniel Veillard01fa6152004-06-29 17:04:39 +00001482
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001483/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001484 * xmlSchemaPErrExt:
1485 * @ctxt: the parsing context
1486 * @node: the context node
1487 * @error: the error code
1488 * @strData1: extra data
1489 * @strData2: extra data
1490 * @strData3: extra data
1491 * @msg: the message
1492 * @str1: extra parameter for the message display
1493 * @str2: extra parameter for the message display
1494 * @str3: extra parameter for the message display
1495 * @str4: extra parameter for the message display
1496 * @str5: extra parameter for the message display
1497 *
1498 * Handle a parser error
1499 */
1500static void
1501xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1502 const xmlChar * strData1, const xmlChar * strData2,
1503 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1504 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1505 const xmlChar * str5)
1506{
1507
1508 xmlGenericErrorFunc channel = NULL;
1509 xmlStructuredErrorFunc schannel = NULL;
1510 void *data = NULL;
1511
1512 if (ctxt != NULL) {
1513 ctxt->nberrors++;
1514 channel = ctxt->error;
1515 data = ctxt->userData;
1516 schannel = ctxt->serror;
1517 }
1518 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1519 error, XML_ERR_ERROR, NULL, 0,
1520 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001521 (const char *) strData3, 0, 0, msg, str1, str2,
1522 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001523}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001525/************************************************************************
1526 * *
1527 * Allround error functions *
1528 * *
1529 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001530
1531/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001532 * xmlSchemaVTypeErrMemory:
1533 * @node: a context node
1534 * @extra: extra informations
1535 *
1536 * Handle an out of memory condition
1537 */
1538static void
1539xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1540 const char *extra, xmlNodePtr node)
1541{
1542 if (ctxt != NULL) {
1543 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001544 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001545 }
1546 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1547 extra);
1548}
1549
1550/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001551 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 * @ctxt: the validation context
1553 * @node: the context node
1554 * @error: the error code
1555 * @msg: the error message
1556 * @str1: extra data
1557 * @str2: extra data
1558 * @str3: extra data
1559 *
1560 * Handle a validation error
1561 */
1562static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001563xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1564 int error, xmlNodePtr node, const char *msg,
1565 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001566{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001567 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001568 xmlGenericErrorFunc channel = NULL;
1569 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571 if (ctxt != NULL) {
1572 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1573 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
1574
1575 vctxt->nberrors++;
1576 vctxt->err = error;
1577 channel = vctxt->error;
1578 schannel = vctxt->serror;
1579 data = vctxt->userData;
1580 if ((node == NULL) && (vctxt->depth >= 0) &&
1581 (vctxt->inode != NULL))
1582 node = vctxt->inode->node;
1583 __xmlRaiseError(schannel, channel, data, ctxt,
1584 node, XML_FROM_SCHEMASV,
1585 error, XML_ERR_ERROR, NULL, 0,
1586 (const char *) str1, (const char *) str2,
1587 (const char *) str3, 0, 0, msg, str1, str2, str3);
1588
1589 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1590 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1591
1592 pctxt->nberrors++;
1593 pctxt->err = error;
1594 channel = pctxt->error;
1595 schannel = pctxt->serror;
1596 data = pctxt->userData;
1597 __xmlRaiseError(schannel, channel, data, ctxt,
1598 node, XML_FROM_SCHEMASP,
1599 error, XML_ERR_ERROR, NULL, 0,
1600 (const char *) str1, (const char *) str2,
1601 (const char *) str3, 0, 0, msg, str1, str2, str3);
1602 } else {
1603 TODO
1604 }
1605 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001606}
1607
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001608static void
1609xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1610 int error, xmlNodePtr node, const char *msg,
1611 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001612{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001613 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001614}
1615
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001616static xmlChar *
1617xmlSchemaFormatNodeForError(xmlChar ** msg,
1618 xmlSchemaAbstractCtxtPtr actxt,
1619 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001620{
1621 xmlChar *str = NULL;
1622
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001623 if (node != NULL) {
1624 /*
1625 * Work on tree nodes.
1626 */
1627 if (node->type == XML_ATTRIBUTE_NODE) {
1628 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001629
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001630 *msg = xmlStrdup(BAD_CAST "Element '");
1631 if (elem->ns != NULL)
1632 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1633 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001634 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001635 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1636 NULL, elem->name));
1637 FREE_AND_NULL(str);
1638 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1639 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1640 } else {
1641 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001642 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001643 if (node->ns != NULL)
1644 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1645 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001646 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001647 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1648 NULL, node->name));
1649 FREE_AND_NULL(str);
1650 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1651 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1652 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1653 /*
1654 * Work on node infos.
1655 */
1656 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1657 xmlSchemaNodeInfoPtr ielem =
1658 vctxt->elemInfos[vctxt->depth];
1659
1660 *msg = xmlStrdup(BAD_CAST "Element '");
1661 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1662 ielem->nsName, ielem->localName));
1663 FREE_AND_NULL(str);
1664 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1665 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1666 } else {
1667 *msg = xmlStrdup(BAD_CAST "Element '");
1668 }
1669 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1670 vctxt->inode->nsName, vctxt->inode->localName));
1671 FREE_AND_NULL(str);
1672 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1673 } else {
1674 TODO
1675 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001676 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001677 /*
1678 * VAL TODO: The output of the given schema component is currently
1679 * disabled.
1680 */
1681#if 0
1682 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1683 *msg = xmlStrcat(*msg, BAD_CAST " [");
1684 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1685 NULL, type, NULL, 0));
1686 FREE_AND_NULL(str)
1687 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001688 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001689#endif
1690 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001691}
1692
Daniel Veillardc0826a72004-08-10 14:17:33 +00001693static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001694xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1695 const char *funcName,
1696 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001697{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001698 xmlChar *msg = NULL;
1699
1700 msg = xmlStrdup(BAD_CAST "Internal error: ");
1701 msg = xmlStrcat(msg, BAD_CAST funcName);
1702 msg = xmlStrcat(msg, BAD_CAST ", ");
1703 msg = xmlStrcat(msg, BAD_CAST message);
1704 msg = xmlStrcat(msg, BAD_CAST ".\n");
1705
1706 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1707 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1708 (const char *) msg, NULL, NULL);
1709
1710 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1711 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1712 (const char *) msg, NULL, NULL);
1713
1714 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001715}
1716
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001717static void
1718xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1719 xmlParserErrors error,
1720 xmlNodePtr node,
1721 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1722 const char *message,
1723 const xmlChar *str1,
1724 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001725{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001726 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001727
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001728 xmlSchemaFormatNodeForError(&msg, actxt, node);
1729 msg = xmlStrcat(msg, (const xmlChar *) message);
1730 msg = xmlStrcat(msg, BAD_CAST ".\n");
1731 xmlSchemaErr(actxt, error, node,
1732 (const char *) msg, str1, str2);
1733 FREE_AND_NULL(msg)
1734}
1735
1736static int
1737xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1738 xmlNodePtr node)
1739{
1740 if (node != NULL)
1741 return (node->type);
1742 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1743 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1744 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1745 return (-1);
1746}
1747
1748static int
1749xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1750{
1751 switch (item->type) {
1752 case XML_SCHEMA_TYPE_COMPLEX:
1753 case XML_SCHEMA_TYPE_SIMPLE:
1754 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1755 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001756 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001757 case XML_SCHEMA_TYPE_GROUP:
1758 return (1);
1759 case XML_SCHEMA_TYPE_ELEMENT:
1760 if ( ((xmlSchemaElementPtr) item)->flags &
1761 XML_SCHEMAS_ELEM_GLOBAL)
1762 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001763 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001764 case XML_SCHEMA_TYPE_ATTRIBUTE:
1765 if ( ((xmlSchemaAttributePtr) item)->flags &
1766 XML_SCHEMAS_ATTR_GLOBAL)
1767 return(1);
1768 break;
1769 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001770 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001771 return(1);
1772 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001773 return (0);
1774}
1775
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001776static void
1777xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1778 xmlParserErrors error,
1779 xmlNodePtr node,
1780 const xmlChar *value,
1781 xmlSchemaTypePtr type,
1782 int displayValue)
1783{
1784 xmlChar *msg = NULL;
1785
1786 xmlSchemaFormatNodeForError(&msg, actxt, node);
1787
1788 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1789 XML_ATTRIBUTE_NODE))
1790 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1791 else
1792 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1793 "value of ");
1794
1795 if (! xmlSchemaIsGlobalItem(type))
1796 msg = xmlStrcat(msg, BAD_CAST "the local ");
1797 else
1798 msg = xmlStrcat(msg, BAD_CAST "the ");
1799
1800 if (VARIETY_ATOMIC(type))
1801 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1802 else if (VARIETY_LIST(type))
1803 msg = xmlStrcat(msg, BAD_CAST "list type");
1804 else if (VARIETY_UNION(type))
1805 msg = xmlStrcat(msg, BAD_CAST "union type");
1806
1807 if (xmlSchemaIsGlobalItem(type)) {
1808 xmlChar *str = NULL;
1809 msg = xmlStrcat(msg, BAD_CAST " '");
1810 if (type->builtInType != 0) {
1811 msg = xmlStrcat(msg, BAD_CAST "xs:");
1812 msg = xmlStrcat(msg, type->name);
1813 } else
1814 msg = xmlStrcat(msg,
1815 xmlSchemaFormatQName(&str,
1816 type->targetNamespace, type->name));
1817 msg = xmlStrcat(msg, BAD_CAST "'");
1818 FREE_AND_NULL(str);
1819 }
1820 msg = xmlStrcat(msg, BAD_CAST ".\n");
1821 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1822 XML_ATTRIBUTE_NODE))
1823 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1824 else
1825 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1826 FREE_AND_NULL(msg)
1827}
1828
Daniel Veillardc0826a72004-08-10 14:17:33 +00001829static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001830xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1831 xmlSchemaNodeInfoPtr ni,
1832 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001833{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001834 if (node != NULL) {
1835 if (node->ns != NULL)
1836 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1837 else
1838 return (xmlSchemaFormatQName(str, NULL, node->name));
1839 } else if (ni != NULL)
1840 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1841 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001842}
1843
Daniel Veillardc0826a72004-08-10 14:17:33 +00001844static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001845xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1846 xmlParserErrors error,
1847 xmlSchemaAttrInfoPtr ni,
1848 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001849{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001850 xmlChar *msg = NULL, *str = NULL;
1851
1852 xmlSchemaFormatNodeForError(&msg, actxt, node);
1853 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1854 xmlSchemaErr(actxt, error, node, (const char *) msg,
1855 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1856 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001857 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001858 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001859}
1860
Daniel Veillardc0826a72004-08-10 14:17:33 +00001861static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001862xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1863 xmlParserErrors error,
1864 xmlNodePtr node,
1865 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001866 const char *message,
1867 int nbval,
1868 int nbneg,
1869 xmlChar **values)
1870{
1871 xmlChar *str = NULL, *msg = NULL;
1872 xmlChar *localName, *nsName;
1873 const xmlChar *cur, *end;
1874 int i;
1875
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001876 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001877 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001878 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001879 /*
1880 * Note that is does not make sense to report that we have a
1881 * wildcard here, since the wildcard might be unfolded into
1882 * multiple transitions.
1883 */
1884 if (nbval + nbneg > 0) {
1885 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001886 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001887 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001888 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001889 nsName = NULL;
1890
1891 for (i = 0; i < nbval + nbneg; i++) {
1892 cur = values[i];
1893 /*
1894 * Get the local name.
1895 */
1896 localName = NULL;
1897
1898 end = cur;
1899 if (*end == '*') {
1900 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001901 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001902 } else {
1903 while ((*end != 0) && (*end != '|'))
1904 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001905 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001906 }
1907 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001908 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001909 /*
1910 * Skip "*|*" if they come with negated expressions, since
1911 * they represent the same negated wildcard.
1912 */
1913 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1914 /*
1915 * Get the namespace name.
1916 */
1917 cur = end;
1918 if (*end == '*') {
1919 nsName = xmlStrdup(BAD_CAST "{*}");
1920 } else {
1921 while (*end != 0)
1922 end++;
1923
1924 if (i >= nbval)
1925 nsName = xmlStrdup(BAD_CAST "{##other:");
1926 else
1927 nsName = xmlStrdup(BAD_CAST "{");
1928
1929 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1930 nsName = xmlStrcat(nsName, BAD_CAST "}");
1931 }
1932 str = xmlStrcat(str, BAD_CAST nsName);
1933 FREE_AND_NULL(nsName)
1934 } else {
1935 FREE_AND_NULL(localName);
1936 continue;
1937 }
1938 }
1939 str = xmlStrcat(str, BAD_CAST localName);
1940 FREE_AND_NULL(localName);
1941
1942 if (i < nbval + nbneg -1)
1943 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001944 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001945 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001946 msg = xmlStrcat(msg, BAD_CAST str);
1947 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001948 } else
1949 msg = xmlStrcat(msg, BAD_CAST "\n");
1950 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001951 xmlFree(msg);
1952}
1953
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001954static void
1955xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1956 xmlParserErrors error,
1957 xmlNodePtr node,
1958 const xmlChar *value,
1959 unsigned long length,
1960 xmlSchemaTypePtr type,
1961 xmlSchemaFacetPtr facet,
1962 const char *message,
1963 const xmlChar *str1,
1964 const xmlChar *str2)
1965{
1966 xmlChar *str = NULL, *msg = NULL;
1967 xmlSchemaTypeType facetType;
1968 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1969
1970 xmlSchemaFormatNodeForError(&msg, actxt, node);
1971 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1972 facetType = XML_SCHEMA_FACET_ENUMERATION;
1973 /*
1974 * If enumerations are validated, one must not expect the
1975 * facet to be given.
1976 */
1977 } else
1978 facetType = facet->type;
1979 msg = xmlStrcat(msg, BAD_CAST "[");
1980 msg = xmlStrcat(msg, BAD_CAST "facet '");
1981 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
1982 msg = xmlStrcat(msg, BAD_CAST "'] ");
1983 if (message == NULL) {
1984 /*
1985 * Use a default message.
1986 */
1987 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1988 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1989 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1990
1991 char len[25], actLen[25];
1992
1993 /* FIXME, TODO: What is the max expected string length of the
1994 * this value?
1995 */
1996 if (nodeType == XML_ATTRIBUTE_NODE)
1997 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1998 else
1999 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2000
2001 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2002 snprintf(actLen, 24, "%lu", length);
2003
2004 if (facetType == XML_SCHEMA_FACET_LENGTH)
2005 msg = xmlStrcat(msg,
2006 BAD_CAST "this differs from the allowed length of '%s'.\n");
2007 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2008 msg = xmlStrcat(msg,
2009 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2010 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2011 msg = xmlStrcat(msg,
2012 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2013
2014 if (nodeType == XML_ATTRIBUTE_NODE)
2015 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2016 value, (const xmlChar *) actLen, (const xmlChar *) len);
2017 else
2018 xmlSchemaErr(actxt, error, node, (const char *) msg,
2019 (const xmlChar *) actLen, (const xmlChar *) len);
2020
2021 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2022 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2023 "of the set {%s}.\n");
2024 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2025 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2026 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2027 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2028 "by the pattern '%s'.\n");
2029 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2030 facet->value);
2031 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2032 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2033 "minimum value allowed ('%s').\n");
2034 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2035 facet->value);
2036 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2037 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2038 "maximum value allowed ('%s').\n");
2039 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2040 facet->value);
2041 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2042 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2043 "'%s'.\n");
2044 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2045 facet->value);
2046 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2047 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2048 "'%s'.\n");
2049 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2050 facet->value);
2051 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2052 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2053 "digits than are allowed ('%s').\n");
2054 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2055 facet->value);
2056 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2057 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2058 "digits than are allowed ('%s').\n");
2059 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2060 facet->value);
2061 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2062 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2063 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2064 } else {
2065 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2066 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2067 }
2068 } else {
2069 msg = xmlStrcat(msg, (const xmlChar *) message);
2070 msg = xmlStrcat(msg, BAD_CAST ".\n");
2071 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2072 }
2073 FREE_AND_NULL(str)
2074 xmlFree(msg);
2075}
2076
2077#define VERROR(err, type, msg) \
2078 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2079
2080#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2081
2082#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2083
2084#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2085
2086
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002087/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002088 * xmlSchemaPMissingAttrErr:
2089 * @ctxt: the schema validation context
2090 * @ownerDes: the designation of the owner
2091 * @ownerName: the name of the owner
2092 * @ownerItem: the owner as a schema object
2093 * @ownerElem: the owner as an element node
2094 * @node: the parent element node of the missing attribute node
2095 * @type: the corresponding type of the attribute node
2096 *
2097 * Reports an illegal attribute.
2098 */
2099static void
2100xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002101 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002102 xmlSchemaTypePtr ownerItem,
2103 xmlNodePtr ownerElem,
2104 const char *name,
2105 const char *message)
2106{
2107 xmlChar *des = NULL;
2108
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002109 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2110
Daniel Veillardc0826a72004-08-10 14:17:33 +00002111 if (message != NULL)
2112 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002113 else
2114 xmlSchemaPErr(ctxt, ownerElem, error,
2115 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002116 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002117 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002118}
2119
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002120
Daniel Veillardc0826a72004-08-10 14:17:33 +00002121/**
2122 * xmlSchemaPResCompAttrErr:
2123 * @ctxt: the schema validation context
2124 * @error: the error code
2125 * @ownerDes: the designation of the owner
2126 * @ownerItem: the owner as a schema object
2127 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002128 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002129 * @refName: the referenced local name
2130 * @refURI: the referenced namespace URI
2131 * @message: optional message
2132 *
2133 * Used to report QName attribute values that failed to resolve
2134 * to schema components.
2135 */
2136static void
2137xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002138 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002139 xmlSchemaTypePtr ownerItem,
2140 xmlNodePtr ownerElem,
2141 const char *name,
2142 const xmlChar *refName,
2143 const xmlChar *refURI,
2144 xmlSchemaTypeType refType,
2145 const char *refTypeStr)
2146{
2147 xmlChar *des = NULL, *strA = NULL;
2148
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002149 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002150 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002151 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2152 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002153 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002154 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2155 "%s.\n", BAD_CAST des, BAD_CAST name,
2156 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002157 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002158 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002159 FREE_AND_NULL(strA)
2160}
2161
William M. Brack2f2a6632004-08-20 23:09:47 +00002162/**
2163 * xmlSchemaPCustomAttrErr:
2164 * @ctxt: the schema parser context
2165 * @error: the error code
2166 * @ownerDes: the designation of the owner
2167 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002168 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002169 *
2170 * Reports an illegal attribute during the parse.
2171 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002172static void
2173xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002174 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002175 xmlChar **ownerDes,
2176 xmlSchemaTypePtr ownerItem,
2177 xmlAttrPtr attr,
2178 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002179{
2180 xmlChar *des = NULL;
2181
2182 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002183 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002184 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002185 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002186 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002187 } else
2188 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002189 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002190 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002191 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2192 if (ownerDes == NULL)
2193 FREE_AND_NULL(des);
2194}
2195
2196/**
2197 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002198 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002199 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002200 * @ownerDes: the designation of the attribute's owner
2201 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002202 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002203 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002204 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002205 */
2206static void
2207xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002208 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002209 xmlChar **ownerDes,
2210 xmlSchemaTypePtr ownerItem,
2211 xmlAttrPtr attr)
2212{
2213 xmlChar *des = NULL, *strA = NULL;
2214
2215 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002216 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002217 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002218 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002219 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002220 } else
2221 des = *ownerDes;
2222 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2223 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2224 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002225 if (ownerDes == NULL)
2226 FREE_AND_NULL(des);
2227 FREE_AND_NULL(strA);
2228}
2229
William M. Brack2f2a6632004-08-20 23:09:47 +00002230/**
2231 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002232 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002233 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002234 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002235 * @itemElem: the node of the schema item
2236 *
2237 * Creates a designation for an item.
2238 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002239static void
2240xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002241 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002242 xmlSchemaTypePtr item,
2243 xmlNodePtr itemElem)
2244{
2245 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002246 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002247 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002248 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002249 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002250 } else
2251 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002252}
2253
William M. Brack2f2a6632004-08-20 23:09:47 +00002254/**
2255 * xmlSchemaPCustomErr:
2256 * @ctxt: the schema parser context
2257 * @error: the error code
2258 * @itemDes: the designation of the schema item
2259 * @item: the schema item
2260 * @itemElem: the node of the schema item
2261 * @message: the error message
2262 * @str1: an optional param for the error message
2263 * @str2: an optional param for the error message
2264 * @str3: an optional param for the error message
2265 *
2266 * Reports an error during parsing.
2267 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002268static void
2269xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002270 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002271 xmlChar **itemDes,
2272 xmlSchemaTypePtr item,
2273 xmlNodePtr itemElem,
2274 const char *message,
2275 const xmlChar *str1,
2276 const xmlChar *str2,
2277 const xmlChar *str3)
2278{
2279 xmlChar *des = NULL, *msg = NULL;
2280
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002281 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002282 msg = xmlStrdup(BAD_CAST "%s: ");
2283 msg = xmlStrcat(msg, (const xmlChar *) message);
2284 msg = xmlStrcat(msg, BAD_CAST ".\n");
2285 if ((itemElem == NULL) && (item != NULL))
2286 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002287 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002288 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2289 if (itemDes == NULL)
2290 FREE_AND_NULL(des);
2291 FREE_AND_NULL(msg);
2292}
2293
William M. Brack2f2a6632004-08-20 23:09:47 +00002294/**
2295 * xmlSchemaPCustomErr:
2296 * @ctxt: the schema parser context
2297 * @error: the error code
2298 * @itemDes: the designation of the schema item
2299 * @item: the schema item
2300 * @itemElem: the node of the schema item
2301 * @message: the error message
2302 * @str1: the optional param for the error message
2303 *
2304 * Reports an error during parsing.
2305 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002306static void
2307xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002308 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002309 xmlChar **itemDes,
2310 xmlSchemaTypePtr item,
2311 xmlNodePtr itemElem,
2312 const char *message,
2313 const xmlChar *str1)
2314{
2315 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2316 str1, NULL, NULL);
2317}
2318
William M. Brack2f2a6632004-08-20 23:09:47 +00002319/**
2320 * xmlSchemaPAttrUseErr:
2321 * @ctxt: the schema parser context
2322 * @error: the error code
2323 * @itemDes: the designation of the schema type
2324 * @item: the schema type
2325 * @itemElem: the node of the schema type
2326 * @attr: the invalid schema attribute
2327 * @message: the error message
2328 * @str1: the optional param for the error message
2329 *
2330 * Reports an attribute use error during parsing.
2331 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002332static void
2333xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002334 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002335 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002336 const xmlSchemaAttributePtr attr,
2337 const char *message,
2338 const xmlChar *str1)
2339{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002340 xmlChar *str = NULL, *msg = NULL;
2341 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2342 msg = xmlStrcat(msg, BAD_CAST ", ");
2343 msg = xmlStrcat(msg,
2344 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2345 (xmlSchemaTypePtr) attr, NULL));
2346 FREE_AND_NULL(str);
2347 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002348 msg = xmlStrcat(msg, (const xmlChar *) message);
2349 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002350 xmlSchemaPErr(ctxt, attr->node, error,
2351 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002352 xmlFree(msg);
2353}
2354
William M. Brack2f2a6632004-08-20 23:09:47 +00002355/**
2356 * xmlSchemaPIllegalFacetAtomicErr:
2357 * @ctxt: the schema parser context
2358 * @error: the error code
2359 * @itemDes: the designation of the type
2360 * @item: the schema type
2361 * @baseItem: the base type of type
2362 * @facet: the illegal facet
2363 *
2364 * Reports an illegal facet for atomic simple types.
2365 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002366static void
2367xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002368 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002369 xmlChar **itemDes,
2370 xmlSchemaTypePtr item,
2371 xmlSchemaTypePtr baseItem,
2372 xmlSchemaFacetPtr facet)
2373{
2374 xmlChar *des = NULL, *strT = NULL;
2375
2376 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2377 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2378 "%s: The facet '%s' is not allowed on types derived from the "
2379 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002380 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002381 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002382 NULL, NULL);
2383 if (itemDes == NULL)
2384 FREE_AND_NULL(des);
2385 FREE_AND_NULL(strT);
2386}
2387
William M. Brack2f2a6632004-08-20 23:09:47 +00002388/**
2389 * xmlSchemaPIllegalFacetListUnionErr:
2390 * @ctxt: the schema parser context
2391 * @error: the error code
2392 * @itemDes: the designation of the schema item involved
2393 * @item: the schema item involved
2394 * @facet: the illegal facet
2395 *
2396 * Reports an illegal facet for <list> and <union>.
2397 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002398static void
2399xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002400 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002401 xmlChar **itemDes,
2402 xmlSchemaTypePtr item,
2403 xmlSchemaFacetPtr facet)
2404{
2405 xmlChar *des = NULL, *strT = NULL;
2406
2407 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002408 xmlSchemaPErr(ctxt, item->node, error,
2409 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002410 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002411 if (itemDes == NULL)
2412 FREE_AND_NULL(des);
2413 FREE_AND_NULL(strT);
2414}
2415
2416/**
2417 * xmlSchemaPMutualExclAttrErr:
2418 * @ctxt: the schema validation context
2419 * @error: the error code
2420 * @elemDes: the designation of the parent element node
2421 * @attr: the bad attribute node
2422 * @type: the corresponding type of the attribute node
2423 *
2424 * Reports an illegal attribute.
2425 */
2426static void
2427xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2428 xmlParserErrors error,
2429 xmlChar **ownerDes,
2430 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002431 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002432 const char *name1,
2433 const char *name2)
2434{
2435 xmlChar *des = NULL;
2436
2437 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002438 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002439 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002440 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002441 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002442 } else
2443 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002444 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002445 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002446 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2447 if (ownerDes == NULL)
2448 FREE_AND_NULL(des)
2449}
2450
2451/**
2452 * xmlSchemaPSimpleTypeErr:
2453 * @ctxt: the schema validation context
2454 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002455 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002456 * @ownerDes: the designation of the owner
2457 * @ownerItem: the schema object if existent
2458 * @node: the validated node
2459 * @value: the validated value
2460 *
2461 * Reports a simple type validation error.
2462 * TODO: Should this report the value of an element as well?
2463 */
2464static void
2465xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2466 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002467 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002468 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002469 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002470 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002471 const xmlChar *value,
2472 const char *message,
2473 const xmlChar *str1,
2474 const xmlChar *str2)
2475{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002476 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002477
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002478 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002479 if (message == NULL) {
2480 /*
2481 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002482 */
2483 if (type != NULL) {
2484 if (node->type == XML_ATTRIBUTE_NODE)
2485 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2486 else
2487 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2488 "valid value of ");
2489 if (! xmlSchemaIsGlobalItem(type))
2490 msg = xmlStrcat(msg, BAD_CAST "the local ");
2491 else
2492 msg = xmlStrcat(msg, BAD_CAST "the ");
2493
2494 if (VARIETY_ATOMIC(type))
2495 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2496 else if (VARIETY_LIST(type))
2497 msg = xmlStrcat(msg, BAD_CAST "list type");
2498 else if (VARIETY_UNION(type))
2499 msg = xmlStrcat(msg, BAD_CAST "union type");
2500
2501 if (xmlSchemaIsGlobalItem(type)) {
2502 xmlChar *str = NULL;
2503 msg = xmlStrcat(msg, BAD_CAST " '");
2504 if (type->builtInType != 0) {
2505 msg = xmlStrcat(msg, BAD_CAST "xs:");
2506 msg = xmlStrcat(msg, type->name);
2507 } else
2508 msg = xmlStrcat(msg,
2509 xmlSchemaFormatQName(&str,
2510 type->targetNamespace, type->name));
2511 msg = xmlStrcat(msg, BAD_CAST "'.");
2512 FREE_AND_NULL(str);
2513 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002514 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002515 if (node->type == XML_ATTRIBUTE_NODE)
2516 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2517 else
2518 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2519 "valid.");
2520 }
2521 if (expected) {
2522 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2523 msg = xmlStrcat(msg, BAD_CAST expected);
2524 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2525 } else
2526 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002527 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002528 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2529 else
2530 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2531 } else {
2532 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2533 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002534 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002535 /* Cleanup. */
2536 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002537}
2538
William M. Brack2f2a6632004-08-20 23:09:47 +00002539/**
2540 * xmlSchemaPContentErr:
2541 * @ctxt: the schema parser context
2542 * @error: the error code
2543 * @onwerDes: the designation of the holder of the content
2544 * @ownerItem: the owner item of the holder of the content
2545 * @ownerElem: the node of the holder of the content
2546 * @child: the invalid child node
2547 * @message: the optional error message
2548 * @content: the optional string describing the correct content
2549 *
2550 * Reports an error concerning the content of a schema element.
2551 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002552static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002553xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002554 xmlParserErrors error,
2555 xmlChar **ownerDes,
2556 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002557 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002558 xmlNodePtr child,
2559 const char *message,
2560 const char *content)
2561{
2562 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002563
Daniel Veillardc0826a72004-08-10 14:17:33 +00002564 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002565 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002566 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002567 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002568 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002569 } else
2570 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002571 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002572 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2573 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002574 BAD_CAST des, BAD_CAST message);
2575 else {
2576 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002577 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2578 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002579 BAD_CAST des, BAD_CAST content);
2580 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002581 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2582 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002583 BAD_CAST des, NULL);
2584 }
2585 }
2586 if (ownerDes == NULL)
2587 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002588}
2589
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002590/************************************************************************
2591 * *
2592 * Streamable error functions *
2593 * *
2594 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002595
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002596
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002597
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002598
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002599/************************************************************************
2600 * *
2601 * Validation helper functions *
2602 * *
2603 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002604
Daniel Veillardc0826a72004-08-10 14:17:33 +00002605
Daniel Veillard4255d502002-04-16 15:50:10 +00002606/************************************************************************
2607 * *
2608 * Allocation functions *
2609 * *
2610 ************************************************************************/
2611
2612/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002613 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002614 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002615 *
2616 * Allocate a new Schema structure.
2617 *
2618 * Returns the newly allocated structure or NULL in case or error
2619 */
2620static xmlSchemaPtr
2621xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2622{
2623 xmlSchemaPtr ret;
2624
2625 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2626 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002627 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002628 return (NULL);
2629 }
2630 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002631 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002632 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002633
2634 return (ret);
2635}
2636
2637/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002638 * xmlSchemaNewSchema:
2639 * @ctxt: a schema validation context
2640 *
2641 * Allocate a new Schema structure.
2642 *
2643 * Returns the newly allocated structure or NULL in case or error
2644 */
2645static xmlSchemaAssemblePtr
2646xmlSchemaNewAssemble(void)
2647{
2648 xmlSchemaAssemblePtr ret;
2649
2650 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2651 if (ret == NULL) {
2652 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2653 return (NULL);
2654 }
2655 memset(ret, 0, sizeof(xmlSchemaAssemble));
2656 ret->items = NULL;
2657 return (ret);
2658}
2659
2660/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002661 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002662 *
2663 * Allocate a new Facet structure.
2664 *
2665 * Returns the newly allocated structure or NULL in case or error
2666 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002667xmlSchemaFacetPtr
2668xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002669{
2670 xmlSchemaFacetPtr ret;
2671
2672 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2673 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002674 return (NULL);
2675 }
2676 memset(ret, 0, sizeof(xmlSchemaFacet));
2677
2678 return (ret);
2679}
2680
2681/**
2682 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002683 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002684 * @node: a node
2685 *
2686 * Allocate a new annotation structure.
2687 *
2688 * Returns the newly allocated structure or NULL in case or error
2689 */
2690static xmlSchemaAnnotPtr
2691xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2692{
2693 xmlSchemaAnnotPtr ret;
2694
2695 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2696 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002697 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002698 return (NULL);
2699 }
2700 memset(ret, 0, sizeof(xmlSchemaAnnot));
2701 ret->content = node;
2702 return (ret);
2703}
2704
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002705static xmlSchemaItemListPtr
2706xmlSchemaNewItemList(void)
2707{
2708 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002709
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002710 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2711 if (ret == NULL) {
2712 xmlSchemaPErrMemory(NULL,
2713 "allocating an item list structure", NULL);
2714 return (NULL);
2715 }
2716 memset(ret, 0, sizeof(xmlSchemaItemList));
2717 return (ret);
2718}
2719
2720/**
2721 * xmlSchemaAddElementSubstitutionMember:
2722 * @pctxt: a schema parser context
2723 * @head: the head of the substitution group
2724 * @member: the new member of the substitution group
2725 *
2726 * Allocate a new annotation structure.
2727 *
2728 * Returns the newly allocated structure or NULL in case or error
2729 */
2730static int
2731xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2732 xmlSchemaElementPtr head,
2733 xmlSchemaElementPtr member)
2734{
2735 xmlSchemaSubstGroupPtr substGroup;
2736
2737 if (pctxt == NULL)
2738 return (-1);
2739
2740 if (pctxt->substGroups == NULL) {
2741 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2742 if (pctxt->substGroups == NULL)
2743 return (-1);
2744 }
2745 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2746 head->targetNamespace);
2747 if (substGroup == NULL) {
2748 int res;
2749
2750 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2751 if (substGroup == NULL) {
2752 xmlSchemaPErrMemory(NULL,
2753 "xmlSchemaAddElementSubstitution, allocating a substitution "
2754 "group container",
2755 NULL);
2756 return (-1);
2757 }
2758 substGroup->members = xmlSchemaNewItemList();
2759 if (substGroup->members == NULL) {
2760 xmlFree(substGroup);
2761 return (-1);
2762 }
2763 substGroup->head = head;
2764
2765 res = xmlHashAddEntry2(pctxt->substGroups,
2766 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002767 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002768 xmlFree(substGroup->members);
2769 xmlFree(substGroup);
2770 xmlSchemaPErr(pctxt, member->node,
2771 XML_SCHEMAP_INTERNAL,
2772 "Internal error: xmlSchemaAddElementSubstitution, "
2773 "failed to add a new substitution group container for "
2774 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002775 return (-1);
2776 }
2777 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002778 if (substGroup->members->items == NULL) {
2779 substGroup->members->items = (void **) xmlMalloc(
2780 5 * sizeof(xmlSchemaElementPtr));
2781 if (substGroup->members->items == NULL) {
2782 xmlSchemaPErrMemory(NULL,
2783 "allocating list of substitution group members", NULL);
2784 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002785 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002786 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002787 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002788 substGroup->members->nbItems) {
2789 substGroup->members->sizeItems *= 2;
2790 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002791 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002792 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2793 if (substGroup->members->items == NULL) {
2794 xmlSchemaPErrMemory(NULL,
2795 "re-allocating list of substitution group members", NULL);
2796 substGroup->members->sizeItems = 0;
2797 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002798 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002799 }
2800 ((xmlSchemaElementPtr *) substGroup->members->items)
2801 [substGroup->members->nbItems++] = (void *) member;
2802 return (0);
2803}
2804
2805/**
2806 * xmlSchemaGetElementSubstitutionGroup:
2807 * @pctxt: a schema parser context
2808 * @head: the head of the substitution group
2809 * @member: the new member of the substitution group
2810 *
2811 * Allocate a new annotation structure.
2812 *
2813 * Returns the newly allocated structure or NULL in case or error
2814 */
2815static xmlSchemaSubstGroupPtr
2816xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2817 xmlSchemaElementPtr head)
2818{
2819 if (pctxt == NULL)
2820 return (NULL);
2821
2822 if (pctxt->substGroups == NULL)
2823 return (NULL);
2824
2825 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2826 head->name, head->targetNamespace));
2827}
2828
2829/**
2830 * xmlSchemaFreeItemList:
2831 * @annot: a schema type structure
2832 *
2833 * Deallocate a annotation structure
2834 */
2835static void
2836xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2837{
2838 if (list == NULL)
2839 return;
2840 if (list->items != NULL)
2841 xmlFree(list->items);
2842 xmlFree(list);
2843}
2844
Daniel Veillard4255d502002-04-16 15:50:10 +00002845/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002846 * xmlSchemaFreeAnnot:
2847 * @annot: a schema type structure
2848 *
2849 * Deallocate a annotation structure
2850 */
2851static void
2852xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2853{
2854 if (annot == NULL)
2855 return;
2856 xmlFree(annot);
2857}
2858
2859/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002860 * xmlSchemaFreeImport:
2861 * @import: a schema import structure
2862 *
2863 * Deallocate an import structure
2864 */
2865static void
2866xmlSchemaFreeImport(xmlSchemaImportPtr import)
2867{
2868 if (import == NULL)
2869 return;
2870
2871 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002872 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002873 xmlFree(import);
2874}
2875
2876/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002877 * xmlSchemaFreeInclude:
2878 * @include: a schema include structure
2879 *
2880 * Deallocate an include structure
2881 */
2882static void
2883xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2884{
2885 if (include == NULL)
2886 return;
2887
2888 xmlFreeDoc(include->doc);
2889 xmlFree(include);
2890}
2891
2892/**
2893 * xmlSchemaFreeIncludeList:
2894 * @includes: a schema include list
2895 *
2896 * Deallocate an include structure
2897 */
2898static void
2899xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2900{
2901 xmlSchemaIncludePtr next;
2902
2903 while (includes != NULL) {
2904 next = includes->next;
2905 xmlSchemaFreeInclude(includes);
2906 includes = next;
2907 }
2908}
2909
2910/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002911 * xmlSchemaFreeNotation:
2912 * @schema: a schema notation structure
2913 *
2914 * Deallocate a Schema Notation structure.
2915 */
2916static void
2917xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2918{
2919 if (nota == NULL)
2920 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002921 xmlFree(nota);
2922}
2923
2924/**
2925 * xmlSchemaFreeAttribute:
2926 * @schema: a schema attribute structure
2927 *
2928 * Deallocate a Schema Attribute structure.
2929 */
2930static void
2931xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2932{
2933 if (attr == NULL)
2934 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002935 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002936 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002937 if (attr->defVal != NULL)
2938 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002939 xmlFree(attr);
2940}
2941
2942/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002943 * xmlSchemaFreeWildcardNsSet:
2944 * set: a schema wildcard namespace
2945 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002946 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002947 */
2948static void
2949xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2950{
2951 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002952
Daniel Veillard3646d642004-06-02 19:19:14 +00002953 while (set != NULL) {
2954 next = set->next;
2955 xmlFree(set);
2956 set = next;
2957 }
2958}
2959
2960/**
2961 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002962 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002963 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002964 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002965 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002966void
Daniel Veillard3646d642004-06-02 19:19:14 +00002967xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2968{
2969 if (wildcard == NULL)
2970 return;
2971 if (wildcard->annot != NULL)
2972 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002973 if (wildcard->nsSet != NULL)
2974 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2975 if (wildcard->negNsSet != NULL)
2976 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002977 xmlFree(wildcard);
2978}
2979
2980/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002981 * xmlSchemaFreeAttributeGroup:
2982 * @schema: a schema attribute group structure
2983 *
2984 * Deallocate a Schema Attribute Group structure.
2985 */
2986static void
2987xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2988{
2989 if (attr == NULL)
2990 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002991 if (attr->annot != NULL)
2992 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002993 xmlFree(attr);
2994}
2995
2996/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002997 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002998 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002999 *
3000 * Deallocate a list of schema attribute uses.
3001 */
3002static void
3003xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3004{
3005 xmlSchemaAttributeLinkPtr next;
3006
3007 while (attrUse != NULL) {
3008 next = attrUse->next;
3009 xmlFree(attrUse);
3010 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003011 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003012}
3013
3014/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003015 * xmlSchemaFreeQNameRef:
3016 * @item: a QName reference structure
3017 *
3018 * Deallocatea a QName reference structure.
3019 */
3020static void
3021xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3022{
3023 xmlFree(item);
3024}
3025
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003026/**
3027 * xmlSchemaFreeQNameRef:
3028 * @item: a QName reference structure
3029 *
3030 * Deallocatea a QName reference structure.
3031 */
3032static void
3033xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3034{
3035 if (item == NULL)
3036 return;
3037 if (item->members != NULL)
3038 xmlSchemaFreeItemList(item->members);
3039 xmlFree(item);
3040}
3041
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003042static int
3043xmlSchemaAddVolatile(xmlSchemaPtr schema,
3044 xmlSchemaBasicItemPtr item)
3045{
3046 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003047
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003048 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003049 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003050 if (schema->volatiles == NULL) {
3051 xmlSchemaPErrMemory(NULL,
3052 "allocating list of volatiles", NULL);
3053 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003054 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003055 }
3056 list = (xmlSchemaItemListPtr) schema->volatiles;
3057 if (list->items == NULL) {
3058 list->items = (void **) xmlMalloc(
3059 20 * sizeof(xmlSchemaBasicItemPtr));
3060 if (list->items == NULL) {
3061 xmlSchemaPErrMemory(NULL,
3062 "allocating new volatile item buffer", NULL);
3063 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003064 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003065 list->sizeItems = 20;
3066 } else if (list->sizeItems <= list->nbItems) {
3067 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003068 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003069 list->sizeItems * sizeof(xmlSchemaTypePtr));
3070 if (list->items == NULL) {
3071 xmlSchemaPErrMemory(NULL,
3072 "growing volatile item buffer", NULL);
3073 list->sizeItems = 0;
3074 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003075 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003076 }
3077 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3078 return (0);
3079}
3080
3081/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003082 * xmlSchemaFreeTypeLinkList:
3083 * @alink: a type link
3084 *
3085 * Deallocate a list of types.
3086 */
3087static void
3088xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3089{
3090 xmlSchemaTypeLinkPtr next;
3091
3092 while (link != NULL) {
3093 next = link->next;
3094 xmlFree(link);
3095 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003096 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003097}
3098
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003099static void
3100xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3101{
3102 xmlSchemaIDCStateObjPtr next;
3103 while (sto != NULL) {
3104 next = sto->next;
3105 if (sto->history != NULL)
3106 xmlFree(sto->history);
3107 if (sto->xpathCtxt != NULL)
3108 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3109 xmlFree(sto);
3110 sto = next;
3111 }
3112}
3113
3114/**
3115 * xmlSchemaFreeIDC:
3116 * @idc: a identity-constraint definition
3117 *
3118 * Deallocates an identity-constraint definition.
3119 */
3120static void
3121xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3122{
3123 xmlSchemaIDCSelectPtr cur, prev;
3124
3125 if (idcDef == NULL)
3126 return;
3127 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003128 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003129 /* Selector */
3130 if (idcDef->selector != NULL) {
3131 if (idcDef->selector->xpathComp != NULL)
3132 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3133 xmlFree(idcDef->selector);
3134 }
3135 /* Fields */
3136 if (idcDef->fields != NULL) {
3137 cur = idcDef->fields;
3138 do {
3139 prev = cur;
3140 cur = cur->next;
3141 if (prev->xpathComp != NULL)
3142 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003143 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003144 } while (cur != NULL);
3145 }
3146 xmlFree(idcDef);
3147}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003148
Daniel Veillard01fa6152004-06-29 17:04:39 +00003149/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003150 * xmlSchemaFreeElement:
3151 * @schema: a schema element structure
3152 *
3153 * Deallocate a Schema Element structure.
3154 */
3155static void
3156xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3157{
3158 if (elem == NULL)
3159 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003160 if (elem->annot != NULL)
3161 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003162 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003163 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003164 if (elem->defVal != NULL)
3165 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003166 xmlFree(elem);
3167}
3168
3169/**
3170 * xmlSchemaFreeFacet:
3171 * @facet: a schema facet structure
3172 *
3173 * Deallocate a Schema Facet structure.
3174 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003175void
Daniel Veillard4255d502002-04-16 15:50:10 +00003176xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3177{
3178 if (facet == NULL)
3179 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003180 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003181 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003182 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003183 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003184 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003185 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003186 xmlFree(facet);
3187}
3188
3189/**
3190 * xmlSchemaFreeType:
3191 * @type: a schema type structure
3192 *
3193 * Deallocate a Schema Type structure.
3194 */
3195void
3196xmlSchemaFreeType(xmlSchemaTypePtr type)
3197{
3198 if (type == NULL)
3199 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003201 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003202 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003203 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003204
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003205 facet = type->facets;
3206 while (facet != NULL) {
3207 next = facet->next;
3208 xmlSchemaFreeFacet(facet);
3209 facet = next;
3210 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003211 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003212 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3213 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003214 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003215 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003216 if (type->memberTypes != NULL)
3217 xmlSchemaFreeTypeLinkList(type->memberTypes);
3218 if (type->facetSet != NULL) {
3219 xmlSchemaFacetLinkPtr next, link;
3220
3221 link = type->facetSet;
3222 do {
3223 next = link->next;
3224 xmlFree(link);
3225 link = next;
3226 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003227 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003228 if (type->contModel != NULL)
3229 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003230 xmlFree(type);
3231}
3232
3233/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003234 * xmlSchemaFreeModelGroupDef:
3235 * @item: a schema model group definition
3236 *
3237 * Deallocates a schema model group definition.
3238 */
3239static void
3240xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3241{
3242 if (item->annot != NULL)
3243 xmlSchemaFreeAnnot(item->annot);
3244 xmlFree(item);
3245}
3246
3247/**
3248 * xmlSchemaFreeModelGroup:
3249 * @item: a schema model group
3250 *
3251 * Deallocates a schema model group structure.
3252 */
3253static void
3254xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3255{
3256 if (item->annot != NULL)
3257 xmlSchemaFreeAnnot(item->annot);
3258 xmlFree(item);
3259}
3260
3261/**
3262 * xmlSchemaFreeParticle:
3263 * @type: a schema type structure
3264 *
3265 * Deallocate a Schema Type structure.
3266 */
3267static void
3268xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3269{
3270 if (item->annot != NULL)
3271 xmlSchemaFreeAnnot(item->annot);
3272 xmlFree(item);
3273}
3274
3275/**
3276 * xmlSchemaFreeMiscComponents:
3277 * @item: a schema component
3278 *
3279 * Deallocates misc. schema component structures.
3280 */
3281static void
3282xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3283{
3284 if (item == NULL)
3285 return;
3286 switch (item->type) {
3287 case XML_SCHEMA_TYPE_PARTICLE:
3288 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3289 return;
3290 case XML_SCHEMA_TYPE_SEQUENCE:
3291 case XML_SCHEMA_TYPE_CHOICE:
3292 case XML_SCHEMA_TYPE_ALL:
3293 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3294 return;
3295 case XML_SCHEMA_TYPE_ANY:
3296 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3297 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3298 break;
3299 default:
3300 /* TODO: This should never be hit. */
3301 TODO
3302 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003303 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003304}
3305
3306static void
3307xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3308{
3309 if (schema->volatiles == NULL)
3310 return;
3311 {
3312 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3313 xmlSchemaTreeItemPtr item;
3314 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003315
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003316 for (i = 0; i < list->nbItems; i++) {
3317 if (list->items[i] != NULL) {
3318 item = (xmlSchemaTreeItemPtr) list->items[i];
3319 switch (item->type) {
3320 case XML_SCHEMA_EXTRA_QNAMEREF:
3321 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3322 break;
3323 default:
3324 xmlSchemaFreeMiscComponents(item);
3325 }
3326 }
3327 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003328 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003329 }
3330}
3331/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003332 * xmlSchemaFreeTypeList:
3333 * @type: a schema type structure
3334 *
3335 * Deallocate a Schema Type structure.
3336 */
3337static void
3338xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3339{
3340 xmlSchemaTypePtr next;
3341
3342 while (type != NULL) {
3343 next = type->redef;
3344 xmlSchemaFreeType(type);
3345 type = next;
3346 }
3347}
3348
3349/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003350 * xmlSchemaFree:
3351 * @schema: a schema structure
3352 *
3353 * Deallocate a Schema structure.
3354 */
3355void
3356xmlSchemaFree(xmlSchemaPtr schema)
3357{
3358 if (schema == NULL)
3359 return;
3360
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003361 if (schema->volatiles != NULL)
3362 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003363 if (schema->notaDecl != NULL)
3364 xmlHashFree(schema->notaDecl,
3365 (xmlHashDeallocator) xmlSchemaFreeNotation);
3366 if (schema->attrDecl != NULL)
3367 xmlHashFree(schema->attrDecl,
3368 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3369 if (schema->attrgrpDecl != NULL)
3370 xmlHashFree(schema->attrgrpDecl,
3371 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3372 if (schema->elemDecl != NULL)
3373 xmlHashFree(schema->elemDecl,
3374 (xmlHashDeallocator) xmlSchemaFreeElement);
3375 if (schema->typeDecl != NULL)
3376 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003377 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003378 if (schema->groupDecl != NULL)
3379 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003380 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003381 if (schema->idcDef != NULL)
3382 xmlHashFree(schema->idcDef,
3383 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003384 if (schema->schemasImports != NULL)
3385 xmlHashFree(schema->schemasImports,
3386 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003387 if (schema->includes != NULL) {
3388 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3389 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003390 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003391 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003392 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003393 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003394 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003395 xmlFree(schema);
3396}
3397
3398/************************************************************************
3399 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003400 * Debug functions *
3401 * *
3402 ************************************************************************/
3403
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003404#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003405
Daniel Veillard4255d502002-04-16 15:50:10 +00003406/**
3407 * xmlSchemaElementDump:
3408 * @elem: an element
3409 * @output: the file output
3410 *
3411 * Dump the element
3412 */
3413static void
3414xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003415 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003416 const xmlChar * namespace ATTRIBUTE_UNUSED,
3417 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003418{
3419 if (elem == NULL)
3420 return;
3421
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003422 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3423 fprintf(output, "Particle: %s", name);
3424 fprintf(output, ", term element: %s", elem->ref);
3425 if (elem->refNs != NULL)
3426 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003427 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003428 fprintf(output, "Element");
3429 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3430 fprintf(output, " (global)");
3431 fprintf(output, ": %s ", elem->name);
3432 if (namespace != NULL)
3433 fprintf(output, "ns %s", namespace);
3434 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003435 fprintf(output, "\n");
3436 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003437 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003438 if (elem->maxOccurs >= UNBOUNDED)
3439 fprintf(output, "max: unbounded\n");
3440 else if (elem->maxOccurs != 1)
3441 fprintf(output, "max: %d\n", elem->maxOccurs);
3442 else
3443 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003444 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003445 /*
3446 * Misc other properties.
3447 */
3448 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3449 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3450 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3451 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3452 (elem->id != NULL)) {
3453 fprintf(output, " props: ");
3454 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3455 fprintf(output, "[fixed] ");
3456 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3457 fprintf(output, "[default] ");
3458 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3459 fprintf(output, "[abstract] ");
3460 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3461 fprintf(output, "[nillable] ");
3462 if (elem->id != NULL)
3463 fprintf(output, "[id: '%s'] ", elem->id);
3464 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003465 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003466 /*
3467 * Default/fixed value.
3468 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003469 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003470 fprintf(output, " value: '%s'\n", elem->value);
3471 /*
3472 * Type.
3473 */
3474 if (elem->namedType != NULL) {
3475 fprintf(output, " type: %s ", elem->namedType);
3476 if (elem->namedTypeNs != NULL)
3477 fprintf(output, "ns %s\n", elem->namedTypeNs);
3478 else
3479 fprintf(output, "\n");
3480 }
3481 /*
3482 * Substitution group.
3483 */
3484 if (elem->substGroup != NULL) {
3485 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3486 if (elem->substGroupNs != NULL)
3487 fprintf(output, "ns %s\n", elem->substGroupNs);
3488 else
3489 fprintf(output, "\n");
3490 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003491}
3492
3493/**
3494 * xmlSchemaAnnotDump:
3495 * @output: the file output
3496 * @annot: a annotation
3497 *
3498 * Dump the annotation
3499 */
3500static void
3501xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3502{
3503 xmlChar *content;
3504
3505 if (annot == NULL)
3506 return;
3507
3508 content = xmlNodeGetContent(annot->content);
3509 if (content != NULL) {
3510 fprintf(output, " Annot: %s\n", content);
3511 xmlFree(content);
3512 } else
3513 fprintf(output, " Annot: empty\n");
3514}
3515
3516/**
3517 * xmlSchemaTypeDump:
3518 * @output: the file output
3519 * @type: a type structure
3520 *
3521 * Dump a SchemaType structure
3522 */
3523static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003524xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3525{
3526 xmlChar *str = NULL;
3527 xmlSchemaTreeItemPtr term;
3528 char shift[100];
3529 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003530
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003531 if (particle == NULL)
3532 return;
3533 for (i = 0;((i < depth) && (i < 25));i++)
3534 shift[2 * i] = shift[2 * i + 1] = ' ';
3535 shift[2 * i] = shift[2 * i + 1] = 0;
3536 fprintf(output, shift);
3537 if (particle->children == NULL) {
3538 fprintf(output, "MISSING particle term\n");
3539 return;
3540 }
3541 term = particle->children;
3542 switch (term->type) {
3543 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003544 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003545 ((xmlSchemaElementPtr)term)->targetNamespace,
3546 ((xmlSchemaElementPtr)term)->name));
3547 break;
3548 case XML_SCHEMA_TYPE_SEQUENCE:
3549 fprintf(output, "SEQUENCE");
3550 break;
3551 case XML_SCHEMA_TYPE_CHOICE:
3552 fprintf(output, "CHOICE");
3553 break;
3554 case XML_SCHEMA_TYPE_ALL:
3555 fprintf(output, "ALL");
3556 break;
3557 case XML_SCHEMA_TYPE_ANY:
3558 fprintf(output, "ANY");
3559 break;
3560 default:
3561 fprintf(output, "UNKNOWN\n");
3562 return;
3563 }
3564 if (particle->minOccurs != 1)
3565 fprintf(output, " min: %d", particle->minOccurs);
3566 if (particle->maxOccurs >= UNBOUNDED)
3567 fprintf(output, " max: unbounded");
3568 else if (particle->maxOccurs != 1)
3569 fprintf(output, " max: %d", particle->maxOccurs);
3570 fprintf(output, "\n");
3571 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3572 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3573 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3574 (term->children != NULL)) {
3575 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3576 output, depth +1);
3577 }
3578 if (particle->next != NULL)
3579 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3580 output, depth);
3581}
3582/**
3583 * xmlSchemaTypeDump:
3584 * @output: the file output
3585 * @type: a type structure
3586 *
3587 * Dump a SchemaType structure
3588 */
3589static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003590xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3591{
3592 if (type == NULL) {
3593 fprintf(output, "Type: NULL\n");
3594 return;
3595 }
3596 fprintf(output, "Type: ");
3597 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003598 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003599 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003600 fprintf(output, "no name ");
3601 if (type->targetNamespace != NULL)
3602 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003603 switch (type->type) {
3604 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003605 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003606 break;
3607 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003608 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003609 break;
3610 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003611 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003612 break;
3613 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003614 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 break;
3616 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003617 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003618 break;
3619 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003620 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 break;
3622 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003623 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003624 break;
3625 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003626 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 break;
3628 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003629 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003630 break;
3631 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003632 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003633 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003634 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003635 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003636 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003637 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003638 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003639 break;
3640 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003641 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003642 break;
3643 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003644 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003645 break;
3646 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003647 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003648 break;
3649 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003650 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003651 break;
3652 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003653 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003654 break;
3655 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003656 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003657 break;
3658 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003659 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003660 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003661 }
3662 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003663 if (type->base != NULL) {
3664 fprintf(output, " base type: %s", type->base);
3665 if (type->baseNs != NULL)
3666 fprintf(output, " ns %s\n", type->baseNs);
3667 else
3668 fprintf(output, "\n");
3669 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003670 if (type->annot != NULL)
3671 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003672#ifdef DUMP_CONTENT_MODEL
3673 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3674 (type->subtypes != NULL)) {
3675 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3676 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003677 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003678#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003679}
3680
3681/**
3682 * xmlSchemaDump:
3683 * @output: the file output
3684 * @schema: a schema structure
3685 *
3686 * Dump a Schema structure.
3687 */
3688void
3689xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3690{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003691 if (output == NULL)
3692 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003693 if (schema == NULL) {
3694 fprintf(output, "Schemas: NULL\n");
3695 return;
3696 }
3697 fprintf(output, "Schemas: ");
3698 if (schema->name != NULL)
3699 fprintf(output, "%s, ", schema->name);
3700 else
3701 fprintf(output, "no name, ");
3702 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003703 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003704 else
3705 fprintf(output, "no target namespace");
3706 fprintf(output, "\n");
3707 if (schema->annot != NULL)
3708 xmlSchemaAnnotDump(output, schema->annot);
3709
3710 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3711 output);
3712 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003713 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003714}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003715
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003716#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003717/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003718 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003719 * @vctxt: the WXS validation context
3720 *
3721 * Displays the current IDC table for debug purposes.
3722 */
3723static void
3724xmlSchemaDebugDumpIDCTable(FILE * output,
3725 const xmlChar *namespaceName,
3726 const xmlChar *localName,
3727 xmlSchemaPSVIIDCBindingPtr bind)
3728{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003729 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003730 xmlSchemaPSVIIDCNodePtr tab;
3731 xmlSchemaPSVIIDCKeyPtr key;
3732 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003733
3734 fprintf(output, "IDC: TABLES on %s\n",
3735 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003736 FREE_AND_NULL(str)
3737
3738 if (bind == NULL)
3739 return;
3740 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003741 fprintf(output, "IDC: BINDING %s\n",
3742 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003743 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003744 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003745 for (i = 0; i < bind->nbNodes; i++) {
3746 tab = bind->nodeTable[i];
3747 fprintf(output, " ( ");
3748 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003749 key = tab->keys[j];
3750 if ((key != NULL) && (key->val != NULL)) {
3751 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003752 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003753 fprintf(output, "\"%s\" ", value);
3754 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003755 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003756 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003757 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003758 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003759 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003760 else
3761 fprintf(output, "(key missing), ");
3762 }
3763 fprintf(output, ")\n");
3764 }
3765 bind = bind->next;
3766 } while (bind != NULL);
3767}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003768#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003769#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003770
3771/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003772 * *
3773 * Utilities *
3774 * *
3775 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003776
Daniel Veillardc0826a72004-08-10 14:17:33 +00003777/**
3778 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003779 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003780 * @name: the name of the attribute
3781 *
3782 * Seeks an attribute with a name of @name in
3783 * no namespace.
3784 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003785 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003786 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003787static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003788xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003789{
3790 xmlAttrPtr prop;
3791
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003792 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003793 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003794 prop = node->properties;
3795 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003796 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003797 return(prop);
3798 prop = prop->next;
3799 }
3800 return (NULL);
3801}
3802
3803/**
3804 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003805 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003806 * @uri: the uri
3807 * @name: the name of the attribute
3808 *
3809 * Seeks an attribute with a local name of @name and
3810 * a namespace URI of @uri.
3811 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003812 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003813 */
3814static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003815xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003816{
3817 xmlAttrPtr prop;
3818
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003819 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003820 return(NULL);
3821 prop = node->properties;
3822 while (prop != NULL) {
3823 if ((prop->ns != NULL) &&
3824 xmlStrEqual(prop->name, BAD_CAST name) &&
3825 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003826 return(prop);
3827 prop = prop->next;
3828 }
3829 return (NULL);
3830}
3831
3832static const xmlChar *
3833xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3834{
3835 xmlChar *val;
3836 const xmlChar *ret;
3837
3838 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003839 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003840 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003841 ret = xmlDictLookup(ctxt->dict, val, -1);
3842 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003843 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003844}
3845
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003846/**
3847 * xmlSchemaGetProp:
3848 * @ctxt: the parser context
3849 * @node: the node
3850 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003851 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003852 * Read a attribute value and internalize the string
3853 *
3854 * Returns the string or NULL if not present.
3855 */
3856static const xmlChar *
3857xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3858 const char *name)
3859{
3860 xmlChar *val;
3861 const xmlChar *ret;
3862
3863 val = xmlGetProp(node, BAD_CAST name);
3864 if (val == NULL)
3865 return(NULL);
3866 ret = xmlDictLookup(ctxt->dict, val, -1);
3867 xmlFree(val);
3868 return(ret);
3869}
3870
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003871/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003872 * *
3873 * Parsing functions *
3874 * *
3875 ************************************************************************/
3876
3877/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003878 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003879 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003880 * @name: the element name
3881 * @ns: the element namespace
3882 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003883 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003884 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003885 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003886 */
3887static xmlSchemaElementPtr
3888xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003889 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003890{
3891 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003892
3893 if ((name == NULL) || (schema == NULL))
3894 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003895
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003896 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003897 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003898 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003899 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003900 } else
3901 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003902 /*
3903 * This one was removed, since top level element declarations have
3904 * the target namespace specified in targetNamespace of the <schema>
3905 * information element, even if elementFormDefault is "unqualified".
3906 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003907
William M. Bracke7091952004-05-11 15:09:58 +00003908 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003909 if (xmlStrEqual(namespace, schema->targetNamespace))
3910 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3911 else
3912 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003913 if ((ret != NULL) &&
3914 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003915 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003916 }
William M. Bracke7091952004-05-11 15:09:58 +00003917 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003918
William M. Brack2f2a6632004-08-20 23:09:47 +00003919 /*
3920 * Removed since imported components will be hold by the main schema only.
3921 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003922 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003923 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003924 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003925 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003926 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003927 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003928 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3929 return (ret);
3930 } else
3931 ret = NULL;
3932 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003933 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003934#ifdef DEBUG
3935 if (ret == NULL) {
3936 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003937 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003938 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003939 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003940 namespace);
3941 }
3942#endif
3943 return (ret);
3944}
3945
3946/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003947 * xmlSchemaGetType:
3948 * @schema: the schemas context
3949 * @name: the type name
3950 * @ns: the type namespace
3951 *
3952 * Lookup a type in the schemas or the predefined types
3953 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003954 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003955 */
3956static xmlSchemaTypePtr
3957xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003958 const xmlChar * namespace)
3959{
Daniel Veillard4255d502002-04-16 15:50:10 +00003960 xmlSchemaTypePtr ret;
3961
3962 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003963 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003964 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003965 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003966 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003967 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003968 }
3969 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003970 if (ret != NULL)
3971 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003972 /*
3973 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003974 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003975 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003976 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003977 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003978 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003979 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003980 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003981 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3982 return (ret);
3983 } else
3984 ret = NULL;
3985 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003986 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003987#ifdef DEBUG
3988 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003989 if (namespace == NULL)
3990 fprintf(stderr, "Unable to lookup type %s", name);
3991 else
3992 fprintf(stderr, "Unable to lookup type %s:%s", name,
3993 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003994 }
3995#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003996 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003997}
3998
Daniel Veillard3646d642004-06-02 19:19:14 +00003999/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004000 * xmlSchemaGetAttributeDecl:
4001 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004002 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004003 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004004 *
4005 * Lookup a an attribute in the schema or imported schemas
4006 *
4007 * Returns the attribute declaration or NULL if not found.
4008 */
4009static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004010xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004011 const xmlChar * namespace)
4012{
4013 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004014
4015 if ((name == NULL) || (schema == NULL))
4016 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004017
4018
Daniel Veillard3646d642004-06-02 19:19:14 +00004019 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4020 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004021 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004022 else
4023 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004024 /*
4025 * Removed, since imported components will be hold by the main schema only.
4026 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004027 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004028 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004029 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004030 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004031 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004032 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004033 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4034 return (ret);
4035 } else
4036 ret = NULL;
4037 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004038 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004039#ifdef DEBUG
4040 if (ret == NULL) {
4041 if (namespace == NULL)
4042 fprintf(stderr, "Unable to lookup attribute %s", name);
4043 else
4044 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4045 namespace);
4046 }
4047#endif
4048 return (ret);
4049}
4050
4051/**
4052 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004053 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004054 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004055 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004056 *
4057 * Lookup a an attribute group in the schema or imported schemas
4058 *
4059 * Returns the attribute group definition or NULL if not found.
4060 */
4061static xmlSchemaAttributeGroupPtr
4062xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4063 const xmlChar * namespace)
4064{
4065 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004066
4067 if ((name == NULL) || (schema == NULL))
4068 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004069
4070
Daniel Veillard3646d642004-06-02 19:19:14 +00004071 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4072 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004073 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004074 else
4075 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004076 /*
4077 * Removed since imported components will be hold by the main schema only.
4078 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004079 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004080 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004081 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004082 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004083 if (import != NULL) {
4084 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4085 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4086 return (ret);
4087 else
4088 ret = NULL;
4089 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004090 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004091#ifdef DEBUG
4092 if (ret == NULL) {
4093 if (namespace == NULL)
4094 fprintf(stderr, "Unable to lookup attribute group %s", name);
4095 else
4096 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4097 namespace);
4098 }
4099#endif
4100 return (ret);
4101}
4102
4103/**
4104 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004105 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004106 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004107 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004108 *
4109 * Lookup a group in the schema or imported schemas
4110 *
4111 * Returns the group definition or NULL if not found.
4112 */
4113static xmlSchemaTypePtr
4114xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4115 const xmlChar * namespace)
4116{
4117 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004118
4119 if ((name == NULL) || (schema == NULL))
4120 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004121
Daniel Veillard3646d642004-06-02 19:19:14 +00004122 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004123 /*
4124 * Removed since imported components will be hold by the main schema only.
4125 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004126 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004127 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004128 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004129 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004130 if (import != NULL) {
4131 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4132 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4133 return (ret);
4134 else
4135 ret = NULL;
4136 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004137 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004138#ifdef DEBUG
4139 if (ret == NULL) {
4140 if (namespace == NULL)
4141 fprintf(stderr, "Unable to lookup group %s", name);
4142 else
4143 fprintf(stderr, "Unable to lookup group %s:%s", name,
4144 namespace);
4145 }
4146#endif
4147 return (ret);
4148}
4149
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004150/**
4151 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004152 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004153 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004154 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004155 *
4156 * Lookup a group in the schema or imported schemas
4157 *
4158 * Returns the group definition or NULL if not found.
4159 */
4160static xmlSchemaTreeItemPtr
4161xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4162 xmlSchemaTypeType itemType,
4163 const xmlChar *name,
4164 const xmlChar *targetNs)
4165{
4166 switch (itemType) {
4167 case XML_SCHEMA_TYPE_GROUP:
4168 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4169 name, targetNs));
4170 case XML_SCHEMA_TYPE_ELEMENT:
4171 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4172 name, targetNs));
4173 default:
4174 return (NULL);
4175 }
4176}
4177
Daniel Veillard4255d502002-04-16 15:50:10 +00004178/************************************************************************
4179 * *
4180 * Parsing functions *
4181 * *
4182 ************************************************************************/
4183
4184#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004185 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004186
4187/**
4188 * xmlSchemaIsBlank:
4189 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004190 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004191 *
4192 * Check if a string is ignorable
4193 *
4194 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4195 */
4196static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004197xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004198{
Daniel Veillard4255d502002-04-16 15:50:10 +00004199 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004200 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004201 if (len < 0) {
4202 while (*str != 0) {
4203 if (!(IS_BLANK_CH(*str)))
4204 return (0);
4205 str++;
4206 }
4207 } else while ((*str != 0) && (len != 0)) {
4208 if (!(IS_BLANK_CH(*str)))
4209 return (0);
4210 str++;
4211 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004212 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004213
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004214 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004215}
4216
4217/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004218 * xmlSchemaAddAssembledItem:
4219 * @ctxt: a schema parser context
4220 * @schema: the schema being built
4221 * @item: the item
4222 *
4223 * Add a item to the schema's list of current items.
4224 * This is used if the schema was already constructed and
4225 * new schemata need to be added to it.
4226 * *WARNING* this interface is highly subject to change.
4227 *
4228 * Returns 0 if suceeds and -1 if an internal error occurs.
4229 */
4230static int
4231xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4232 xmlSchemaTypePtr item)
4233{
4234 static int growSize = 100;
4235 xmlSchemaAssemblePtr ass;
4236
4237 ass = ctxt->assemble;
4238 if (ass->sizeItems < 0) {
4239 /* If disabled. */
4240 return (0);
4241 }
4242 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004243 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004244 if (ass->items == NULL) {
4245 xmlSchemaPErrMemory(ctxt,
4246 "allocating new item buffer", NULL);
4247 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004248 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004249 ass->sizeItems = growSize;
4250 } else if (ass->sizeItems <= ass->nbItems) {
4251 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004252 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004253 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4254 if (ass->items == NULL) {
4255 xmlSchemaPErrMemory(ctxt,
4256 "growing item buffer", NULL);
4257 ass->sizeItems = 0;
4258 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004259 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004260 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004261 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004262 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4263 return (0);
4264}
4265
4266/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004267 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004268 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004269 * @schema: the schema being built
4270 * @name: the item name
4271 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004272 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004273 * *WARNING* this interface is highly subject to change
4274 *
4275 * Returns the new struture or NULL in case of error
4276 */
4277static xmlSchemaNotationPtr
4278xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004279 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004280{
4281 xmlSchemaNotationPtr ret = NULL;
4282 int val;
4283
4284 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4285 return (NULL);
4286
4287 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004288 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004289 if (schema->notaDecl == NULL)
4290 return (NULL);
4291
4292 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4293 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004294 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004295 return (NULL);
4296 }
4297 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004298 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004299 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4300 ret);
4301 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004302 /*
4303 * TODO: This should never happen, since a unique name will be computed.
4304 * If it fails, then an other internal error must have occured.
4305 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004306 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4307 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004308 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004310 xmlFree(ret);
4311 return (NULL);
4312 }
4313 return (ret);
4314}
4315
4316
4317/**
4318 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004319 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004320 * @schema: the schema being built
4321 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004322 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004323 *
4324 * Add an XML schema Attrribute declaration
4325 * *WARNING* this interface is highly subject to change
4326 *
4327 * Returns the new struture or NULL in case of error
4328 */
4329static xmlSchemaAttributePtr
4330xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004331 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004332 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004333{
4334 xmlSchemaAttributePtr ret = NULL;
4335 int val;
4336
4337 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4338 return (NULL);
4339
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004340#ifdef DEBUG
4341 fprintf(stderr, "Adding attribute %s\n", name);
4342 if (namespace != NULL)
4343 fprintf(stderr, " target namespace %s\n", namespace);
4344#endif
4345
Daniel Veillard4255d502002-04-16 15:50:10 +00004346 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004347 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004348 if (schema->attrDecl == NULL)
4349 return (NULL);
4350
4351 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4352 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004353 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 return (NULL);
4355 }
4356 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004357 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004358 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004359 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004360 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004361 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004362 if (topLevel) {
4363 xmlSchemaPCustomErr(ctxt,
4364 XML_SCHEMAP_REDEFINED_ATTR,
4365 NULL, NULL, node,
4366 "A global attribute declaration with the name '%s' does "
4367 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004368 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004369 return (NULL);
4370 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004371 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004372 /*
4373 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4374 * in the scenario:
4375 * 1. multiple top-level complex types have different target
4376 * namespaces but have the SAME NAME; this can happen if
4377 * schemata are imported
4378 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004379 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004380 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004381 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004382 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004383 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004384 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004385
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004386 if (val != 0) {
4387 xmlSchemaPCustomErr(ctxt,
4388 XML_SCHEMAP_INTERNAL,
4389 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004390 "Internal error: xmlSchemaAddAttribute, "
4391 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004392 "could not be added to the hash.", name);
4393 xmlFree(ret);
4394 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004395 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004396 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004397 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004398 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004399 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004400 return (ret);
4401}
4402
4403/**
4404 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004405 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004406 * @schema: the schema being built
4407 * @name: the item name
4408 *
4409 * Add an XML schema Attrribute Group declaration
4410 *
4411 * Returns the new struture or NULL in case of error
4412 */
4413static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004414xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004415 xmlSchemaPtr schema, const xmlChar * name,
4416 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004417{
4418 xmlSchemaAttributeGroupPtr ret = NULL;
4419 int val;
4420
4421 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4422 return (NULL);
4423
4424 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004425 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004426 if (schema->attrgrpDecl == NULL)
4427 return (NULL);
4428
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004429 ret =
4430 (xmlSchemaAttributeGroupPtr)
4431 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004432 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004433 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004434 return (NULL);
4435 }
4436 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004437 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004438 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004439 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004441 xmlSchemaPCustomErr(ctxt,
4442 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4443 NULL, NULL, node,
4444 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004445 xmlFree(ret);
4446 return (NULL);
4447 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004448 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004449 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004450 return (ret);
4451}
4452
4453/**
4454 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004455 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004456 * @schema: the schema being built
4457 * @name: the type name
4458 * @namespace: the type namespace
4459 *
4460 * Add an XML schema Element declaration
4461 * *WARNING* this interface is highly subject to change
4462 *
4463 * Returns the new struture or NULL in case of error
4464 */
4465static xmlSchemaElementPtr
4466xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004467 const xmlChar * name, const xmlChar * namespace,
4468 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004469{
4470 xmlSchemaElementPtr ret = NULL;
4471 int val;
4472
4473 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4474 return (NULL);
4475
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004476#ifdef DEBUG
4477 fprintf(stderr, "Adding element %s\n", name);
4478 if (namespace != NULL)
4479 fprintf(stderr, " target namespace %s\n", namespace);
4480#endif
4481
Daniel Veillard4255d502002-04-16 15:50:10 +00004482 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004483 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004484 if (schema->elemDecl == NULL)
4485 return (NULL);
4486
4487 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4488 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004489 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004490 return (NULL);
4491 }
4492 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004493 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004494 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004495 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004496 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004497 if (topLevel) {
4498 xmlSchemaPCustomErr(ctxt,
4499 XML_SCHEMAP_REDEFINED_ELEMENT,
4500 NULL, NULL, node,
4501 "A global element declaration with the name '%s' does "
4502 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503 xmlFree(ret);
4504 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004505 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004506 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004507
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004508 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004509 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004510 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004511 if (val != 0) {
4512 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004513 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004514 NULL, NULL, node,
4515 "Internal error: xmlSchemaAddElement, "
4516 "a dublicate element declaration with the name '%s' "
4517 "could not be added to the hash.", name);
4518 xmlFree(ret);
4519 return (NULL);
4520 }
4521 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004522
Daniel Veillard4255d502002-04-16 15:50:10 +00004523 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004524 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004525 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004526 return (ret);
4527}
4528
4529/**
4530 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004531 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004532 * @schema: the schema being built
4533 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004534 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004535 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004536 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004537 * *WARNING* this interface is highly subject to change
4538 *
4539 * Returns the new struture or NULL in case of error
4540 */
4541static xmlSchemaTypePtr
4542xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004543 const xmlChar * name, const xmlChar * namespace,
4544 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004545{
4546 xmlSchemaTypePtr ret = NULL;
4547 int val;
4548
4549 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4550 return (NULL);
4551
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004552#ifdef DEBUG
4553 fprintf(stderr, "Adding type %s\n", name);
4554 if (namespace != NULL)
4555 fprintf(stderr, " target namespace %s\n", namespace);
4556#endif
4557
Daniel Veillard4255d502002-04-16 15:50:10 +00004558 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004559 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004560 if (schema->typeDecl == NULL)
4561 return (NULL);
4562
4563 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4564 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004565 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004566 return (NULL);
4567 }
4568 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004569 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004570 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004571 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004572 if (val != 0) {
4573 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004574 xmlSchemaPCustomErr(ctxt,
4575 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004576 NULL, NULL, node,
4577 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004578 xmlFree(ret);
4579 return (NULL);
4580 } else {
4581 xmlSchemaTypePtr prev;
4582
4583 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4584 if (prev == NULL) {
4585 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004586 XML_ERR_INTERNAL_ERROR,
4587 "Internal error: xmlSchemaAddType, on type "
4588 "'%s'.\n",
4589 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004590 xmlFree(ret);
4591 return (NULL);
4592 }
4593 ret->redef = prev->redef;
4594 prev->redef = ret;
4595 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004596 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004597 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004598 ret->minOccurs = 1;
4599 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004600 ret->attributeUses = NULL;
4601 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004602 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004603 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004604 return (ret);
4605}
4606
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004607static xmlSchemaQNameRefPtr
4608xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4609 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004610 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004611 const xmlChar *refNs)
4612{
4613 xmlSchemaQNameRefPtr ret;
4614
4615 ret = (xmlSchemaQNameRefPtr)
4616 xmlMalloc(sizeof(xmlSchemaQNameRef));
4617 if (ret == NULL) {
4618 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4619 NULL);
4620 return (NULL);
4621 }
4622 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4623 ret->name = refName;
4624 ret->targetNamespace = refNs;
4625 ret->item = NULL;
4626 ret->itemType = refType;
4627 /*
4628 * Store the reference item in the schema.
4629 */
4630 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4631 return (ret);
4632}
4633
4634/**
4635 * xmlSchemaAddModelGroup:
4636 * @ctxt: a schema parser context
4637 * @schema: the schema being built
4638 * @type: the "compositor" type of the model group
4639 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004640 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004641 *
4642 * Adds a schema model group
4643 * *WARNING* this interface is highly subject to change
4644 *
4645 * Returns the new struture or NULL in case of error
4646 */
4647static xmlSchemaModelGroupPtr
4648xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4649 xmlSchemaTypeType type, const xmlChar **container,
4650 xmlNodePtr node)
4651{
4652 xmlSchemaModelGroupPtr ret = NULL;
4653 xmlChar buf[30];
4654
4655 if ((ctxt == NULL) || (schema == NULL))
4656 return (NULL);
4657
4658#ifdef DEBUG
4659 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004660#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004661 ret = (xmlSchemaModelGroupPtr)
4662 xmlMalloc(sizeof(xmlSchemaModelGroup));
4663 if (ret == NULL) {
4664 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4665 NULL);
4666 return (NULL);
4667 }
4668 ret->type = type;
4669 ret->annot = NULL;
4670 ret->node = node;
4671 ret->children = NULL;
4672 ret->next = NULL;
4673 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4674 if (container != NULL)
4675 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4676 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004677 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004678 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4679 } else {
4680 if (container != NULL)
4681 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4682 }
4683 if (container != NULL)
4684 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4685 /*
4686 * Add to volatile items.
4687 * TODO: this should be changed someday.
4688 */
4689 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4690 xmlFree(ret);
4691 return (NULL);
4692 }
4693 return (ret);
4694}
4695
4696
4697/**
4698 * xmlSchemaAddParticle:
4699 * @ctxt: a schema parser context
4700 * @schema: the schema being built
4701 * @node: the corresponding node in the schema doc
4702 * @min: the minOccurs
4703 * @max: the maxOccurs
4704 *
4705 * Adds an XML schema particle component.
4706 * *WARNING* this interface is highly subject to change
4707 *
4708 * Returns the new struture or NULL in case of error
4709 */
4710static xmlSchemaParticlePtr
4711xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4712 xmlNodePtr node, int min, int max)
4713{
4714 xmlSchemaParticlePtr ret = NULL;
4715 if ((ctxt == NULL) || (schema == NULL))
4716 return (NULL);
4717
4718#ifdef DEBUG
4719 fprintf(stderr, "Adding particle component\n");
4720#endif
4721 ret = (xmlSchemaParticlePtr)
4722 xmlMalloc(sizeof(xmlSchemaParticle));
4723 if (ret == NULL) {
4724 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4725 NULL);
4726 return (NULL);
4727 }
4728 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4729 ret->annot = NULL;
4730 ret->node = node;
4731 ret->minOccurs = min;
4732 ret->maxOccurs = max;
4733 ret->next = NULL;
4734 ret->children = NULL;
4735
4736 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4737 xmlFree(ret);
4738 return (NULL);
4739 }
4740 return (ret);
4741}
4742
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004743/**
4744 * xmlSchemaAddGroup:
4745 * @ctxt: a schema validation context
4746 * @schema: the schema being built
4747 * @name: the group name
4748 *
4749 * Add an XML schema Group definition
4750 *
4751 * Returns the new struture or NULL in case of error
4752 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004753static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004754xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004755 const xmlChar *name, const xmlChar *namespaceName,
4756 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004757{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004758 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004759 int val;
4760
4761 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4762 return (NULL);
4763
4764 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004765 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004766 if (schema->groupDecl == NULL)
4767 return (NULL);
4768
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004769 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004770 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004771 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004772 return (NULL);
4773 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004774 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004775 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004776 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004777 ret->node = node;
4778 ret->targetNamespace = namespaceName;
4779 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004780 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004781 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004782 XML_SCHEMAP_REDEFINED_GROUP,
4783 NULL, NULL, node,
4784 "A global model group definition with the name '%s' does already "
4785 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004786 xmlFree(ret);
4787 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004788 }
4789 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004790 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004791 return (ret);
4792}
4793
Daniel Veillard3646d642004-06-02 19:19:14 +00004794/**
4795 * xmlSchemaNewWildcardNs:
4796 * @ctxt: a schema validation context
4797 *
4798 * Creates a new wildcard namespace constraint.
4799 *
4800 * Returns the new struture or NULL in case of error
4801 */
4802static xmlSchemaWildcardNsPtr
4803xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4804{
4805 xmlSchemaWildcardNsPtr ret;
4806
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004807 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004808 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4809 if (ret == NULL) {
4810 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004811 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004812 }
4813 ret->value = NULL;
4814 ret->next = NULL;
4815 return (ret);
4816}
4817
4818/**
4819 * xmlSchemaAddWildcard:
4820 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004821 * @schema: a schema
4822 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004823 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004824 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004825 *
4826 * Returns the new struture or NULL in case of error
4827 */
4828static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004829xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4830 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004831{
4832 xmlSchemaWildcardPtr ret = NULL;
4833
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004834 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004835 return (NULL);
4836
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004837#ifdef DEBUG
4838 fprintf(stderr, "Adding wildcard component\n");
4839#endif
4840
Daniel Veillard3646d642004-06-02 19:19:14 +00004841 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4842 if (ret == NULL) {
4843 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4844 return (NULL);
4845 }
4846 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004847 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004848 ret->minOccurs = 1;
4849 ret->maxOccurs = 1;
4850
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004851 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4852 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4853 "Failed to add a wildcard component to the list", NULL);
4854 xmlFree(ret);
4855 return (NULL);
4856 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004857 return (ret);
4858}
4859
Daniel Veillard4255d502002-04-16 15:50:10 +00004860/************************************************************************
4861 * *
4862 * Utilities for parsing *
4863 * *
4864 ************************************************************************/
4865
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004866#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004867/**
4868 * xmlGetQNameProp:
4869 * @ctxt: a schema validation context
4870 * @node: a subtree containing XML Schema informations
4871 * @name: the attribute name
4872 * @namespace: the result namespace if any
4873 *
4874 * Extract a QName Attribute value
4875 *
4876 * Returns the NCName or NULL if not found, and also update @namespace
4877 * with the namespace URI
4878 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004879static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004880xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004881 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004882{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004883 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004884 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004885 const xmlChar *ret, *prefix;
4886 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004887 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004888
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004889 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004890 attr = xmlSchemaGetPropNode(node, name);
4891 if (attr == NULL)
4892 return (NULL);
4893 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004894
Daniel Veillard4255d502002-04-16 15:50:10 +00004895 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004896 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004897
Daniel Veillardba0153a2004-04-01 10:42:31 +00004898 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004899 ns = xmlSearchNs(node->doc, node, 0);
4900 if (ns) {
4901 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4902 return (val);
4903 }
4904 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004905 ret = xmlSplitQName3(val, &len);
4906 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004907 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004908 }
4909 ret = xmlDictLookup(ctxt->dict, ret, -1);
4910 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004911
4912 ns = xmlSearchNs(node->doc, node, prefix);
4913 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004914 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4915 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004916 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004917 "The QName value '%s' has no corresponding namespace "
4918 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004919 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004920 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004921 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004922 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004923}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004924#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004925
4926/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004927 * xmlSchemaPValAttrNodeQNameValue:
4928 * @ctxt: a schema parser context
4929 * @schema: the schema context
4930 * @ownerDes: the designation of the parent element
4931 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004932 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004933 * @local: the resulting local part if found, the attribute value otherwise
4934 * @uri: the resulting namespace URI if found
4935 *
4936 * Extracts the local name and the URI of a QName value and validates it.
4937 * This one is intended to be used on attribute values that
4938 * should resolve to schema components.
4939 *
4940 * Returns 0, in case the QName is valid, a positive error code
4941 * if not valid and -1 if an internal error occurs.
4942 */
4943static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004944xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004945 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004946 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004947 xmlSchemaTypePtr ownerItem,
4948 xmlAttrPtr attr,
4949 const xmlChar *value,
4950 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004951 const xmlChar **local)
4952{
4953 const xmlChar *pref;
4954 xmlNsPtr ns;
4955 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004956
Daniel Veillardc0826a72004-08-10 14:17:33 +00004957 *uri = NULL;
4958 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004959 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004960 if (ret > 0) {
4961 xmlSchemaPSimpleTypeErr(ctxt,
4962 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4963 ownerItem, (xmlNodePtr) attr,
4964 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4965 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004966 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004967 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004968 } else if (ret < 0)
4969 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004970
4971 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004972 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4973 if (ns)
4974 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4975 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4976 /*
4977 * This one takes care of included schemas with no
4978 * target namespace.
4979 */
4980 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004981 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004982 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004983 return (0);
4984 }
4985 /*
4986 * At this point xmlSplitQName3 has to return a local name.
4987 */
4988 *local = xmlSplitQName3(value, &len);
4989 *local = xmlDictLookup(ctxt->dict, *local, -1);
4990 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4992 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004993 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004994 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004995 ownerItem, (xmlNodePtr) attr,
4996 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
4997 "The value '%s' of simple type 'xs:QName' has no "
4998 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004999 return (ctxt->err);
5000 } else {
5001 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005002 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005003 return (0);
5004}
5005
5006/**
5007 * xmlSchemaPValAttrNodeQName:
5008 * @ctxt: a schema parser context
5009 * @schema: the schema context
5010 * @ownerDes: the designation of the owner element
5011 * @ownerItem: the owner as a schema object
5012 * @attr: the attribute node
5013 * @local: the resulting local part if found, the attribute value otherwise
5014 * @uri: the resulting namespace URI if found
5015 *
5016 * Extracts and validates the QName of an attribute value.
5017 * This one is intended to be used on attribute values that
5018 * should resolve to schema components.
5019 *
5020 * Returns 0, in case the QName is valid, a positive error code
5021 * if not valid and -1 if an internal error occurs.
5022 */
5023static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005024xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005025 xmlSchemaPtr schema,
5026 xmlChar **ownerDes,
5027 xmlSchemaTypePtr ownerItem,
5028 xmlAttrPtr attr,
5029 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005030 const xmlChar **local)
5031{
5032 const xmlChar *value;
5033
5034 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005035 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5036 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005037}
5038
5039/**
5040 * xmlSchemaPValAttrQName:
5041 * @ctxt: a schema parser context
5042 * @schema: the schema context
5043 * @ownerDes: the designation of the parent element
5044 * @ownerItem: the owner as a schema object
5045 * @ownerElem: the parent node of the attribute
5046 * @name: the name of the attribute
5047 * @local: the resulting local part if found, the attribute value otherwise
5048 * @uri: the resulting namespace URI if found
5049 *
5050 * Extracts and validates the QName of an attribute value.
5051 *
5052 * Returns 0, in case the QName is valid, a positive error code
5053 * if not valid and -1 if an internal error occurs.
5054 */
5055static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005056xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5057 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005058 xmlChar **ownerDes,
5059 xmlSchemaTypePtr ownerItem,
5060 xmlNodePtr ownerElem,
5061 const char *name,
5062 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005063 const xmlChar **local)
5064{
5065 xmlAttrPtr attr;
5066
5067 attr = xmlSchemaGetPropNode(ownerElem, name);
5068 if (attr == NULL) {
5069 *local = NULL;
5070 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005071 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005072 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005073 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5074 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005075}
5076
5077/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005078 * xmlSchemaPValAttrID:
5079 * @ctxt: a schema parser context
5080 * @schema: the schema context
5081 * @ownerDes: the designation of the parent element
5082 * @ownerItem: the owner as a schema object
5083 * @ownerElem: the parent node of the attribute
5084 * @name: the name of the attribute
5085 *
5086 * Extracts and validates the ID of an attribute value.
5087 *
5088 * Returns 0, in case the ID is valid, a positive error code
5089 * if not valid and -1 if an internal error occurs.
5090 */
5091static int
5092xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005093 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005094 xmlSchemaTypePtr ownerItem,
5095 xmlNodePtr ownerElem,
5096 const xmlChar *name)
5097{
5098 int ret;
5099 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005100 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005101
5102 value = xmlGetNoNsProp(ownerElem, name);
5103 if (value == NULL)
5104 return (0);
5105
5106 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5107 if (attr == NULL)
5108 return (-1);
5109
5110 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005111 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005112 /*
5113 * NOTE: the IDness might have already be declared in the DTD
5114 */
5115 if (attr->atype != XML_ATTRIBUTE_ID) {
5116 xmlIDPtr res;
5117 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005118
5119 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005120 * TODO: Use xmlSchemaStrip here; it's not exported at this
5121 * moment.
5122 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005123 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005124 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005125 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005126 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5127 if (res == NULL) {
5128 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005129 xmlSchemaPSimpleTypeErr(ctxt,
5130 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5131 ownerItem, (xmlNodePtr) attr,
5132 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5133 NULL, NULL, "Duplicate value '%s' of simple "
5134 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005135 } else
5136 attr->atype = XML_ATTRIBUTE_ID;
5137 if (strip != NULL)
5138 xmlFree(strip);
5139 }
5140 } else if (ret > 0) {
5141 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005142 xmlSchemaPSimpleTypeErr(ctxt,
5143 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5144 ownerItem, (xmlNodePtr) attr,
5145 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5146 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5147 "not a valid 'xs:NCName'",
5148 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005149 }
5150 xmlFree(value);
5151
5152 return (ret);
5153}
5154
5155/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005156 * xmlGetMaxOccurs:
5157 * @ctxt: a schema validation context
5158 * @node: a subtree containing XML Schema informations
5159 *
5160 * Get the maxOccurs property
5161 *
5162 * Returns the default if not found, or the value
5163 */
5164static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005165xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5166 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005167{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005168 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005169 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005170 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005171
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005172 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5173 if (attr == NULL)
5174 return (def);
5175 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005176
5177 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005178 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005179 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005180 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5181 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005182 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005183 val, NULL, NULL, NULL);
5184 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005185 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005186 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005187 }
5188
5189 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005190 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005191 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005192 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005193 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005194 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5195 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005196 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005197 val, NULL, NULL, NULL);
5198 return (def);
5199 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005200 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005201 ret = ret * 10 + (*cur - '0');
5202 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005203 }
William M. Brack76e95df2003-10-18 16:20:14 +00005204 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005205 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005206 /*
5207 * TODO: Restrict the maximal value to Integer.
5208 */
5209 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005210 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005211 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5212 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005213 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005214 val, NULL, NULL, NULL);
5215 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005216 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005217 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005218}
5219
5220/**
5221 * xmlGetMinOccurs:
5222 * @ctxt: a schema validation context
5223 * @node: a subtree containing XML Schema informations
5224 *
5225 * Get the minOccurs property
5226 *
5227 * Returns the default if not found, or the value
5228 */
5229static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005230xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005231 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005232{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005233 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005234 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005235 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005236
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005237 attr = xmlSchemaGetPropNode(node, "minOccurs");
5238 if (attr == NULL)
5239 return (def);
5240 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005241 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005242 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005243 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005244 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005245 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005246 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5247 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005248 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005249 val, NULL, NULL, NULL);
5250 return (def);
5251 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005252 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005253 ret = ret * 10 + (*cur - '0');
5254 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005255 }
William M. Brack76e95df2003-10-18 16:20:14 +00005256 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005257 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005258 /*
5259 * TODO: Restrict the maximal value to Integer.
5260 */
5261 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005262 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005263 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5264 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005265 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005266 val, NULL, NULL, NULL);
5267 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005268 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005269 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005270}
5271
5272/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005273 * xmlSchemaPGetBoolNodeValue:
5274 * @ctxt: a schema validation context
5275 * @ownerDes: owner designation
5276 * @ownerItem: the owner as a schema item
5277 * @node: the node holding the value
5278 *
5279 * Converts a boolean string value into 1 or 0.
5280 *
5281 * Returns 0 or 1.
5282 */
5283static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005284xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5285 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005286 xmlSchemaTypePtr ownerItem,
5287 xmlNodePtr node)
5288{
5289 xmlChar *value = NULL;
5290 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005291
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005292 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005293 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005294 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005295 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005296 * can have the following legal literals {true, false, 1, 0}.
5297 */
5298 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5299 res = 1;
5300 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5301 res = 0;
5302 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5303 res = 1;
5304 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005305 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005306 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005307 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005308 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005309 ownerItem, node,
5310 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5311 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005312 NULL, NULL, NULL);
5313 }
5314 if (value != NULL)
5315 xmlFree(value);
5316 return (res);
5317}
5318
5319/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005320 * xmlGetBooleanProp:
5321 * @ctxt: a schema validation context
5322 * @node: a subtree containing XML Schema informations
5323 * @name: the attribute name
5324 * @def: the default value
5325 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005326 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005327 *
5328 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005329 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005330 */
5331static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005332xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5333 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005334 xmlSchemaTypePtr ownerItem,
5335 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005336 const char *name, int def)
5337{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005338 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005339
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005340 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005341 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005342 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005343 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005344 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005345 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005346 * can have the following legal literals {true, false, 1, 0}.
5347 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005348 if (xmlStrEqual(val, BAD_CAST "true"))
5349 def = 1;
5350 else if (xmlStrEqual(val, BAD_CAST "false"))
5351 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 else if (xmlStrEqual(val, BAD_CAST "1"))
5353 def = 1;
5354 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005355 def = 0;
5356 else {
5357 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005358 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005359 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005360 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005361 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5362 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005363 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005364 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005365}
5366
5367/************************************************************************
5368 * *
5369 * Shema extraction from an Infoset *
5370 * *
5371 ************************************************************************/
5372static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5373 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005374 xmlNodePtr node,
5375 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005376static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5377 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005378 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005379 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005380 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005381static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5382 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005383 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005384 xmlNodePtr node,
5385 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005386static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5387 ctxt,
5388 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005389 xmlNodePtr node,
5390 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005391static xmlSchemaAttributeGroupPtr
5392xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005393 xmlSchemaPtr schema, xmlNodePtr node,
5394 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005395static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5396 xmlSchemaPtr schema,
5397 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005398static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005399xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5400 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005401
5402/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005403 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005404 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005405 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005406 * @ownerDes: the designation of the parent element
5407 * @ownerItem: the schema object owner if existent
5408 * @attr: the schema attribute node being validated
5409 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005410 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005411 *
5412 * Validates a value against the given built-in type.
5413 * This one is intended to be used internally for validation
5414 * of schema attribute values during parsing of the schema.
5415 *
5416 * Returns 0 if the value is valid, a positive error code
5417 * number otherwise and -1 in case of an internal or API error.
5418 */
5419static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005420xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5421 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5422 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005423 xmlAttrPtr attr,
5424 const xmlChar *value,
5425 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005426{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005427
5428 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005429
5430 /*
5431 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5432 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005433 */
5434 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005435 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005436 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5437 PERROR_INT("xmlSchemaPValAttrNodeValue",
5438 "the given type is not a built-in type");
5439 return (-1);
5440 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005441 switch (type->builtInType) {
5442 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005443 case XML_SCHEMAS_QNAME:
5444 case XML_SCHEMAS_ANYURI:
5445 case XML_SCHEMAS_TOKEN:
5446 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005447 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5448 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005449 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005450 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005451 PERROR_INT("xmlSchemaPValAttrNodeValue",
5452 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005453 return (-1);
5454 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005455 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005456 /*
5457 * TODO: Should we use the S4S error codes instead?
5458 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005459 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005460 PERROR_INT("xmlSchemaPValAttrNodeValue",
5461 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005462 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005463 } else if (ret > 0) {
5464 if (VARIETY_LIST(type))
5465 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5466 else
5467 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5468 xmlSchemaPSimpleTypeErr(pctxt,
5469 ret, ownerItem, (xmlNodePtr) attr,
5470 type, NULL, value, NULL, NULL, NULL);
5471 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005472 return (ret);
5473}
5474
5475/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005476 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005477 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005478 * @ctxt: a schema parser context
5479 * @ownerDes: the designation of the parent element
5480 * @ownerItem: the schema object owner if existent
5481 * @attr: the schema attribute node being validated
5482 * @type: the built-in type to be validated against
5483 * @value: the resulting value if any
5484 *
5485 * Extracts and validates a value against the given built-in type.
5486 * This one is intended to be used internally for validation
5487 * of schema attribute values during parsing of the schema.
5488 *
5489 * Returns 0 if the value is valid, a positive error code
5490 * number otherwise and -1 in case of an internal or API error.
5491 */
5492static int
5493xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5494 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005495 xmlSchemaTypePtr ownerItem,
5496 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005497 xmlSchemaTypePtr type,
5498 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005499{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005500 const xmlChar *val;
5501
5502 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005503 return (-1);
5504
Daniel Veillardc0826a72004-08-10 14:17:33 +00005505 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5506 if (value != NULL)
5507 *value = val;
5508
5509 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005510 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005511}
5512
5513/**
5514 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005515 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005516 * @ctxt: a schema parser context
5517 * @node: the element node of the attribute
5518 * @ownerDes: the designation of the parent element
5519 * @ownerItem: the schema object owner if existent
5520 * @ownerElem: the owner element node
5521 * @name: the name of the schema attribute node
5522 * @type: the built-in type to be validated against
5523 * @value: the resulting value if any
5524 *
5525 * Extracts and validates a value against the given built-in type.
5526 * This one is intended to be used internally for validation
5527 * of schema attribute values during parsing of the schema.
5528 *
5529 * Returns 0 if the value is valid, a positive error code
5530 * number otherwise and -1 in case of an internal or API error.
5531 */
5532static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005533xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005534 xmlChar **ownerDes,
5535 xmlSchemaTypePtr ownerItem,
5536 xmlNodePtr ownerElem,
5537 const char *name,
5538 xmlSchemaTypePtr type,
5539 const xmlChar **value)
5540{
5541 xmlAttrPtr attr;
5542
5543 if ((ctxt == NULL) || (type == NULL)) {
5544 if (value != NULL)
5545 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005546 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005547 }
5548 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5549 if (value != NULL)
5550 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005551 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005552 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005553 "Internal error: xmlSchemaPValAttr, the given "
5554 "type '%s' is not a built-in type.\n",
5555 type->name, NULL);
5556 return (-1);
5557 }
5558 attr = xmlSchemaGetPropNode(ownerElem, name);
5559 if (attr == NULL) {
5560 if (value != NULL)
5561 *value = NULL;
5562 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005563 }
5564 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005565 type, value));
5566}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005567
5568static int
5569xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5570 xmlSchemaPtr schema,
5571 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005572 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005573 const xmlChar *namespaceName)
5574{
5575 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005576 return (1);
5577 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5578 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005579 if (pctxt->localImports != NULL) {
5580 int i;
5581 for (i = 0; i < pctxt->nbLocalImports; i++)
5582 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5583 return (1);
5584 }
5585 if (namespaceName == NULL)
5586 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005587 NULL, (xmlSchemaTypePtr) item, node,
5588 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005589 "namespace are not valid, since not indicated by an import "
5590 "statement", NULL);
5591 else
5592 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005593 NULL, (xmlSchemaTypePtr) item, node,
5594 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005595 "namespace '%s' are not valid, since not indicated by an import "
5596 "statement", namespaceName);
5597 return (0);
5598}
5599
Daniel Veillardc0826a72004-08-10 14:17:33 +00005600/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005601 * xmlSchemaParseAttrDecls:
5602 * @ctxt: a schema validation context
5603 * @schema: the schema being built
5604 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005605 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005606 *
5607 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005608 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5610 */
5611static xmlNodePtr
5612xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5613 xmlNodePtr child, xmlSchemaTypePtr type)
5614{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005615 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005616
Daniel Veillard4255d502002-04-16 15:50:10 +00005617 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005618 (IS_SCHEMA(child, "attributeGroup"))) {
5619 attr = NULL;
5620 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005621 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005622 } else if (IS_SCHEMA(child, "attributeGroup")) {
5623 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005624 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005625 }
5626 if (attr != NULL) {
5627 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005628 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5629 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5630 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005631 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005632 lastattr = attr;
5633 } else {
5634 lastattr->next = attr;
5635 lastattr = attr;
5636 }
5637 }
5638 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005639 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005640 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005641}
5642
5643/**
5644 * xmlSchemaParseAnnotation:
5645 * @ctxt: a schema validation context
5646 * @schema: the schema being built
5647 * @node: a subtree containing XML Schema informations
5648 *
5649 * parse a XML schema Attrribute declaration
5650 * *WARNING* this interface is highly subject to change
5651 *
William M. Bracke7091952004-05-11 15:09:58 +00005652 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005653 * 1 in case of success.
5654 */
5655static xmlSchemaAnnotPtr
5656xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5657 xmlNodePtr node)
5658{
5659 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005660 xmlNodePtr child = NULL;
5661 xmlAttrPtr attr;
5662 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005663
Daniel Veillardc0826a72004-08-10 14:17:33 +00005664 /*
5665 * INFO: S4S completed.
5666 */
5667 /*
5668 * id = ID
5669 * {any attributes with non-schema namespace . . .}>
5670 * Content: (appinfo | documentation)*
5671 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005672 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5673 return (NULL);
5674 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005675 attr = node->properties;
5676 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005677 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005678 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005679 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005680 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005681
5682 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005683 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5684 NULL, NULL, attr);
5685 }
5686 attr = attr->next;
5687 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005688 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005689 /*
5690 * And now for the children...
5691 */
5692 child = node->children;
5693 while (child != NULL) {
5694 if (IS_SCHEMA(child, "appinfo")) {
5695 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005696 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005697 * source = anyURI
5698 * {any attributes with non-schema namespace . . .}>
5699 * Content: ({any})*
5700 */
5701 attr = child->properties;
5702 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005703 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005704 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005705 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005706 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005707
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005708 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005709 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5710 NULL, NULL, attr);
5711 }
5712 attr = attr->next;
5713 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005714 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5715 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005716 child = child->next;
5717 } else if (IS_SCHEMA(child, "documentation")) {
5718 /* TODO: make available the content of "documentation". */
5719 /*
5720 * source = anyURI
5721 * {any attributes with non-schema namespace . . .}>
5722 * Content: ({any})*
5723 */
5724 attr = child->properties;
5725 while (attr != NULL) {
5726 if (attr->ns == NULL) {
5727 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005728 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005729 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5730 NULL, NULL, attr);
5731 }
5732 } else {
5733 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5734 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5735 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005736
5737 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005738 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5739 NULL, NULL, attr);
5740 }
5741 }
5742 attr = attr->next;
5743 }
5744 /*
5745 * Attribute "xml:lang".
5746 */
5747 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5748 if (attr != NULL)
5749 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005750 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005751 child = child->next;
5752 } else {
5753 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005754 xmlSchemaPContentErr(ctxt,
5755 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005756 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5757 barked = 1;
5758 child = child->next;
5759 }
5760 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005761
Daniel Veillard4255d502002-04-16 15:50:10 +00005762 return (ret);
5763}
5764
5765/**
5766 * xmlSchemaParseFacet:
5767 * @ctxt: a schema validation context
5768 * @schema: the schema being built
5769 * @node: a subtree containing XML Schema informations
5770 *
5771 * parse a XML schema Facet declaration
5772 * *WARNING* this interface is highly subject to change
5773 *
5774 * Returns the new type structure or NULL in case of error
5775 */
5776static xmlSchemaFacetPtr
5777xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005778 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005779{
5780 xmlSchemaFacetPtr facet;
5781 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005782 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005783
5784 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5785 return (NULL);
5786
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005787 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005788 if (facet == NULL) {
5789 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5790 return (NULL);
5791 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005792 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005793 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005794 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005795 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5796 "Facet %s has no value\n", node->name, NULL);
5797 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005798 return (NULL);
5799 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005800 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005801 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005802 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005803 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005804 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005805 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005806 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005807 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005810 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005811 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005812 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005813 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005814 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005815 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005816 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005817 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005818 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005819 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005820 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005821 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5822 } else if (IS_SCHEMA(node, "minLength")) {
5823 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5824 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005825 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5826 "Unknown facet type %s\n", node->name, NULL);
5827 xmlSchemaFreeFacet(facet);
5828 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005830 xmlSchemaPValAttrID(ctxt, NULL,
5831 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005832 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005833 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5834 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5835 const xmlChar *fixed;
5836
5837 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5838 if (fixed != NULL) {
5839 if (xmlStrEqual(fixed, BAD_CAST "true"))
5840 facet->fixed = 1;
5841 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005842 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005843 child = node->children;
5844
5845 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005846 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5847 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005848 }
5849 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005850 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5851 "Facet %s has unexpected child content\n",
5852 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005853 }
5854 return (facet);
5855}
5856
5857/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005858 * xmlSchemaParseWildcardNs:
5859 * @ctxt: a schema parser context
5860 * @wildc: the wildcard, already created
5861 * @node: a subtree containing XML Schema informations
5862 *
5863 * Parses the attribute "processContents" and "namespace"
5864 * of a xsd:anyAttribute and xsd:any.
5865 * *WARNING* this interface is highly subject to change
5866 *
5867 * Returns 0 if everything goes fine, a positive error code
5868 * if something is not valid and -1 if an internal error occurs.
5869 */
5870static int
5871xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5872 xmlSchemaPtr schema,
5873 xmlSchemaWildcardPtr wildc,
5874 xmlNodePtr node)
5875{
5876 const xmlChar *pc, *ns, *dictnsItem;
5877 int ret = 0;
5878 xmlChar *nsItem;
5879 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5880 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005881
Daniel Veillardc0826a72004-08-10 14:17:33 +00005882 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5883 if ((pc == NULL)
5884 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5885 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5886 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5887 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5888 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5889 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5890 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005891 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005892 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005893 NULL, node,
5894 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005895 NULL, NULL, NULL);
5896 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005897 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005898 }
5899 /*
5900 * Build the namespace constraints.
5901 */
5902 attr = xmlSchemaGetPropNode(node, "namespace");
5903 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005904 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005905 wildc->any = 1;
5906 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5907 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005908 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005909 return (-1);
5910 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005911 wildc->negNsSet->value = schema->targetNamespace;
5912 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005913 const xmlChar *end, *cur;
5914
5915 cur = ns;
5916 do {
5917 while (IS_BLANK_CH(*cur))
5918 cur++;
5919 end = cur;
5920 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5921 end++;
5922 if (end == cur)
5923 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005924 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005925 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5926 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005927 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005928 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005929 NULL, (xmlNodePtr) attr,
5930 NULL,
5931 "((##any | ##other) | List of (xs:anyURI | "
5932 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005933 nsItem, NULL, NULL, NULL);
5934 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5935 } else {
5936 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5937 dictnsItem = schema->targetNamespace;
5938 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5939 dictnsItem = NULL;
5940 } else {
5941 /*
5942 * Validate the item (anyURI).
5943 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005944 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005945 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5946 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5947 }
5948 /*
5949 * Avoid dublicate namespaces.
5950 */
5951 tmp = wildc->nsSet;
5952 while (tmp != NULL) {
5953 if (dictnsItem == tmp->value)
5954 break;
5955 tmp = tmp->next;
5956 }
5957 if (tmp == NULL) {
5958 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5959 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005960 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005961 return (-1);
5962 }
5963 tmp->value = dictnsItem;
5964 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005965 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005966 wildc->nsSet = tmp;
5967 else
5968 lastNs->next = tmp;
5969 lastNs = tmp;
5970 }
5971
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005972 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005973 xmlFree(nsItem);
5974 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005975 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005976 }
5977 return (ret);
5978}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005979
5980static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005981xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5982 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005983 xmlNodePtr node,
5984 int minOccurs,
5985 int maxOccurs) {
5986
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005987 if ((maxOccurs == 0) && ( minOccurs == 0))
5988 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005989 if (maxOccurs != UNBOUNDED) {
5990 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005991 * TODO: Maybe we should better not create the particle,
5992 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005993 * content model.
5994 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005995 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005996 * 3.9.6 Schema Component Constraint: Particle Correct
5997 *
5998 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005999 if (maxOccurs < 1) {
6000 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006001 * 2.2 {max occurs} must be greater than or equal to 1.
6002 */
6003 xmlSchemaPCustomAttrErr(ctxt,
6004 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006005 NULL, NULL,
6006 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006007 "The value must be greater than or equal to 1");
6008 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6009 } else if (minOccurs > maxOccurs) {
6010 /*
6011 * 2.1 {min occurs} must not be greater than {max occurs}.
6012 */
6013 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006014 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006015 NULL, NULL,
6016 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006017 "The value must not be greater than the value of 'maxOccurs'");
6018 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6019 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006020 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006021 return (0);
6022}
6023
Daniel Veillardc0826a72004-08-10 14:17:33 +00006024/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006025 * xmlSchemaParseAny:
6026 * @ctxt: a schema validation context
6027 * @schema: the schema being built
6028 * @node: a subtree containing XML Schema informations
6029 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006030 * Parsea a XML schema <any> element. A particle and wildcard
6031 * will be created (except if minOccurs==maxOccurs==0, in this case
6032 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 * *WARNING* this interface is highly subject to change
6034 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006035 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006036 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006037static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006038xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6039 xmlNodePtr node)
6040{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006041 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006042 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006043 xmlSchemaWildcardPtr wild;
6044 int min, max;
6045 xmlAttrPtr attr;
6046 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006047
6048 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6049 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006050 /*
6051 * Check for illegal attributes.
6052 */
6053 attr = node->properties;
6054 while (attr != NULL) {
6055 if (attr->ns == NULL) {
6056 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6057 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6058 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6059 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6060 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006061 xmlSchemaPIllegalAttrErr(ctxt,
6062 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6063 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006064 }
6065 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006066 xmlSchemaPIllegalAttrErr(ctxt,
6067 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6068 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006069 }
6070 attr = attr->next;
6071 }
6072 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6073 /*
6074 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006075 */
6076 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6077 "(xs:nonNegativeInteger | unbounded)");
6078 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6079 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006080 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6081 /*
6082 * Create & parse the wildcard.
6083 */
6084 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6085 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006086 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006087 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006088 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006089 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006090 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006091 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006092 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006093 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006094 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006095 }
6096 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006097 xmlSchemaPContentErr(ctxt,
6098 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006099 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006100 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006101 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006102 /*
6103 * No component if minOccurs==maxOccurs==0.
6104 */
6105 if ((min == 0) && (max == 0)) {
6106 /* Don't free the wildcard, since it's already on the list. */
6107 return (NULL);
6108 }
6109 /*
6110 * Create the particle.
6111 */
6112 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6113 if (particle == NULL)
6114 return (NULL);
6115 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006116 wild->minOccurs = min;
6117 wild->maxOccurs = max;
6118 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006119
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006120 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006121}
6122
6123/**
6124 * xmlSchemaParseNotation:
6125 * @ctxt: a schema validation context
6126 * @schema: the schema being built
6127 * @node: a subtree containing XML Schema informations
6128 *
6129 * parse a XML schema Notation declaration
6130 *
6131 * Returns the new structure or NULL in case of error
6132 */
6133static xmlSchemaNotationPtr
6134xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006135 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006136{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006137 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006138 xmlSchemaNotationPtr ret;
6139 xmlNodePtr child = NULL;
6140
6141 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6142 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006143 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006144 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006145 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6146 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006147 return (NULL);
6148 }
6149 ret = xmlSchemaAddNotation(ctxt, schema, name);
6150 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006151 return (NULL);
6152 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006153 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006154
6155 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6156 node, BAD_CAST "id");
6157
6158 if (IS_SCHEMA(child, "annotation")) {
6159 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6160 child = child->next;
6161 }
6162
Daniel Veillard4255d502002-04-16 15:50:10 +00006163 child = node->children;
6164 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006165 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6166 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006167 }
6168 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006169 xmlSchemaPContentErr(ctxt,
6170 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006171 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006172 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006173 }
6174
6175 return (ret);
6176}
6177
6178/**
6179 * xmlSchemaParseAnyAttribute:
6180 * @ctxt: a schema validation context
6181 * @schema: the schema being built
6182 * @node: a subtree containing XML Schema informations
6183 *
6184 * parse a XML schema AnyAttrribute declaration
6185 * *WARNING* this interface is highly subject to change
6186 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006187 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006188 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006189static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006190xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6191 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006192{
Daniel Veillard3646d642004-06-02 19:19:14 +00006193 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006194 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006195 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006196
6197 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6198 return (NULL);
6199
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006200 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6201 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 if (ret == NULL) {
6203 return (NULL);
6204 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006205 /*
6206 * Check for illegal attributes.
6207 */
6208 attr = node->properties;
6209 while (attr != NULL) {
6210 if (attr->ns == NULL) {
6211 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6212 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6213 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006214 xmlSchemaPIllegalAttrErr(ctxt,
6215 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6216 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006217 }
6218 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006219 xmlSchemaPIllegalAttrErr(ctxt,
6220 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6221 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006222 }
6223 attr = attr->next;
6224 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006225 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6226 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006227 /*
6228 * Parse the namespace list.
6229 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006230 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006231 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006232 /*
6233 * And now for the children...
6234 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006235 child = node->children;
6236 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006237 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6238 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006239 }
6240 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006241 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006242 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006243 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006244 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006245 }
6246
6247 return (ret);
6248}
6249
6250
6251/**
6252 * xmlSchemaParseAttribute:
6253 * @ctxt: a schema validation context
6254 * @schema: the schema being built
6255 * @node: a subtree containing XML Schema informations
6256 *
6257 * parse a XML schema Attrribute declaration
6258 * *WARNING* this interface is highly subject to change
6259 *
William M. Bracke7091952004-05-11 15:09:58 +00006260 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006261 */
6262static xmlSchemaAttributePtr
6263xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006264 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006265{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006266 const xmlChar *name, *attrValue;
6267 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006268 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006269 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006270 xmlAttrPtr attr, nameAttr;
6271 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006272
6273 /*
6274 * Note that the w3c spec assumes the schema to be validated with schema
6275 * for schemas beforehand.
6276 *
6277 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006278 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006279
6280 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6281 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006282 attr = xmlSchemaGetPropNode(node, "ref");
6283 nameAttr = xmlSchemaGetPropNode(node, "name");
6284
6285 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006286 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006287 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006288 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006289 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006290 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6291 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006292 "One of the attributes 'ref' or 'name' must be present");
6293 return (NULL);
6294 }
6295 if ((topLevel) || (attr == NULL)) {
6296 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006297 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6298 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006299 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006300 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006301 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006302 isRef = 1;
6303
Daniel Veillardc0826a72004-08-10 14:17:33 +00006304 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006305 char buf[50];
6306 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006307
6308 /*
6309 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006310 */
6311 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6312 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6313 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006314 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006315 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006316 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006317 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006318 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006319 if (ret == NULL) {
6320 if (repName != NULL)
6321 xmlFree(repName);
6322 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006323 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006324 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6325 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006326 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006327 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006328 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6329 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006330 /*
6331 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6332 */
6333 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006334 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6335 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006336 "ref", "name");
6337 /*
6338 * Check for illegal attributes.
6339 */
6340 attr = node->properties;
6341 while (attr != NULL) {
6342 if (attr->ns == NULL) {
6343 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6344 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006345 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006346 * 3.2.3 : 3.2
6347 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006348 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006349 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006350 xmlSchemaPIllegalAttrErr(ctxt,
6351 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006352 (xmlSchemaTypePtr) ret, attr);
6353 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6354 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6355 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006356 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6357 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006358 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006359 xmlSchemaPIllegalAttrErr(ctxt,
6360 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6361 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006362 }
6363 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006364 xmlSchemaPIllegalAttrErr(ctxt,
6365 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6366 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006367 }
6368 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006369 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006370 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006371 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006372
Daniel Veillardc0826a72004-08-10 14:17:33 +00006373 /*
6374 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006375 */
6376 if (xmlSchemaPValAttrNode(ctxt,
6377 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006378 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6379 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006380 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006381 /*
6382 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6383 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006384 /*
6385 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6386 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006387 */
6388 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006389 xmlSchemaPSimpleTypeErr(ctxt,
6390 XML_SCHEMAP_NO_XMLNS,
6391 NULL, (xmlNodePtr) nameAttr,
6392 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6393 "The value of type 'xs:NCName' must not match 'xmlns'",
6394 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 if (repName != NULL)
6396 xmlFree(repName);
6397 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006398 }
6399 /*
6400 * Evaluate the target namespace
6401 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006402 if (topLevel) {
6403 ns = schema->targetNamespace;
6404 } else {
6405 attr = xmlSchemaGetPropNode(node, "form");
6406 if (attr != NULL) {
6407 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6408 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6409 ns = schema->targetNamespace;
6410 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006411 xmlSchemaPSimpleTypeErr(ctxt,
6412 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6413 NULL, (xmlNodePtr) attr,
6414 NULL, "(qualified | unqualified)",
6415 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006416 }
6417 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006418 ns = schema->targetNamespace;
6419 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006420 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006421 if (ret == NULL) {
6422 if (repName != NULL)
6423 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006424 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006425 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006426 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006427 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006428 if (topLevel)
6429 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006430 /*
6431 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6432 * TODO: Move this to the component layer.
6433 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006434 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006435 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006436 XML_SCHEMAP_NO_XSI,
6437 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006438 "The target namespace must not match '%s'",
6439 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006440 }
6441 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006442 * Check for illegal attributes.
6443 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006444 attr = node->properties;
6445 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006446 if (attr->ns == NULL) {
6447 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6448 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6449 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006450 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6451 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006452 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006453 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6454 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006455 xmlSchemaPIllegalAttrErr(ctxt,
6456 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6457 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 }
6459 }
6460 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006461 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6462 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006463 }
6464 attr = attr->next;
6465 }
6466 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006467 node, "type", &ret->typeNs, &ret->typeName);
6468 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006469 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6470 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006471 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006472 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006473 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006474 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6475 if (ret->defValue != NULL)
6476 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006477 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006478 * Attribute "default".
6479 */
6480 attr = xmlSchemaGetPropNode(node, "default");
6481 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006482 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006483 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006484 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006485 */
6486 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6487 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6488 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6489 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006490 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6491 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006493 /*
6494 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006495 */
6496 attr = xmlSchemaGetPropNode(node, "use");
6497 if (attr != NULL) {
6498 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6499 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6500 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6501 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6502 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6503 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6504 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6505 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006506 xmlSchemaPSimpleTypeErr(ctxt,
6507 XML_SCHEMAP_INVALID_ATTR_USE,
6508 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6509 NULL, "(optional | prohibited | required)",
6510 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006511 } else
6512 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006513 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006514 * 3.2.3 : 2
6515 * If default and use are both present, use must have
6516 * the actual value optional.
6517 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006518 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6519 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006520 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006521 xmlSchemaPSimpleTypeErr(ctxt,
6522 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6523 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6524 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006525 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006526 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006527 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006528 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006529 /*
6530 * And now for the children...
6531 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006532 child = node->children;
6533 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006534 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6535 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006538 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006539 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006540 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006541 * 3.2.3 : 3.2
6542 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006543 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006544 */
6545 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6546 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6547 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6550 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006551 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006552 }
6553 } else {
6554 if (IS_SCHEMA(child, "simpleType")) {
6555 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006556 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006558 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 */
6560 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6561 &repName, (xmlSchemaTypePtr) ret, node, child,
6562 "The attribute 'type' and the <simpleType> child "
6563 "are mutually exclusive", NULL);
6564 } else
6565 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6566 child = child->next;
6567 }
6568 if (child != NULL)
6569 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6570 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6571 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006572 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006573 /*
6574 * Cleanup.
6575 */
6576 if (repName != NULL)
6577 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006578 return (ret);
6579}
6580
6581/**
6582 * xmlSchemaParseAttributeGroup:
6583 * @ctxt: a schema validation context
6584 * @schema: the schema being built
6585 * @node: a subtree containing XML Schema informations
6586 *
6587 * parse a XML schema Attribute Group declaration
6588 * *WARNING* this interface is highly subject to change
6589 *
6590 * Returns the attribute group or NULL in case of error.
6591 */
6592static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006593xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006594 xmlSchemaPtr schema, xmlNodePtr node,
6595 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006596{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006597 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006598 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006599 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006600 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006601 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006602
6603 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6604 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006605
6606 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006607 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006608 if ((topLevel) || (attr == NULL)) {
6609 /*
6610 * Parse as an attribute group definition.
6611 * Note that those are allowed at top level only.
6612 */
6613 if (nameAttr == NULL) {
6614 xmlSchemaPMissingAttrErr(ctxt,
6615 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006616 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006617 return (NULL);
6618 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006619 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006620 * (xmlNodePtr) nameAttr);
6621 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006622 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006623 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006624 */
6625 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006626 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006627 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6628 return (NULL);
6629 }
6630 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6631 if (ret == NULL)
6632 return (NULL);
6633 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6634 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6635 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006636 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006637 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006638 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006639 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006640
6641 /*
6642 * Parse as an attribute group definition reference.
6643 */
6644 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006645 xmlSchemaPMissingAttrErr(ctxt,
6646 XML_SCHEMAP_S4S_ATTR_MISSING,
6647 NULL, node, "ref", NULL);
6648 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006649 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006650 NULL, NULL, attr, &refNs,&ref);
6651
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006652 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006653 name = (const xmlChar *) buf;
6654 if (name == NULL) {
6655 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6656 "attribute group definition reference", node);
6657 return (NULL);
6658 }
6659 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6660 if (ret == NULL)
6661 return (NULL);
6662 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6663 ret->ref = ref;
6664 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006665 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006666 xmlSchemaCheckReference(ctxt, schema, node,
6667 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006668 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006669 /*
6670 * Check for illegal attributes.
6671 */
6672 attr = node->properties;
6673 while (attr != NULL) {
6674 if (attr->ns == NULL) {
6675 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6676 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006677 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006678 {
6679 xmlSchemaPIllegalAttrErr(ctxt,
6680 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6681 NULL, NULL, attr);
6682 }
6683 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6684 xmlSchemaPIllegalAttrErr(ctxt,
6685 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6686 NULL, NULL, attr);
6687 }
6688 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006689 }
6690 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006691 /*
6692 * And now for the children...
6693 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006694 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006695 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006696 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006697 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006698 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6699 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006700 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006701 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006702 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006703 if (IS_SCHEMA(child, "anyAttribute")) {
6704 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6705 child = child->next;
6706 }
6707 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006708 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006709 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006710 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6711 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006712 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006713 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006714 ctxt->container = oldcontainer;
6715 return (ret);
6716}
6717
6718/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006719 * xmlSchemaPValAttrFormDefault:
6720 * @value: the value
6721 * @flags: the flags to be modified
6722 * @flagQualified: the specific flag for "qualified"
6723 *
6724 * Returns 0 if the value is valid, 1 otherwise.
6725 */
6726static int
6727xmlSchemaPValAttrFormDefault(const xmlChar *value,
6728 int *flags,
6729 int flagQualified)
6730{
6731 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6732 if ((*flags & flagQualified) == 0)
6733 *flags |= flagQualified;
6734 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006735 return (1);
6736
William M. Brack2f2a6632004-08-20 23:09:47 +00006737 return (0);
6738}
6739
6740/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006741 * xmlSchemaPValAttrBlockFinal:
6742 * @value: the value
6743 * @flags: the flags to be modified
6744 * @flagAll: the specific flag for "#all"
6745 * @flagExtension: the specific flag for "extension"
6746 * @flagRestriction: the specific flag for "restriction"
6747 * @flagSubstitution: the specific flag for "substitution"
6748 * @flagList: the specific flag for "list"
6749 * @flagUnion: the specific flag for "union"
6750 *
6751 * Validates the value of the attribute "final" and "block". The value
6752 * is converted into the specified flag values and returned in @flags.
6753 *
6754 * Returns 0 if the value is valid, 1 otherwise.
6755 */
6756
6757static int
6758xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006759 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006760 int flagAll,
6761 int flagExtension,
6762 int flagRestriction,
6763 int flagSubstitution,
6764 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006765 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006766{
6767 int ret = 0;
6768
6769 /*
6770 * TODO: This does not check for dublicate entries.
6771 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006772 if ((flags == NULL) || (value == NULL))
6773 return (-1);
6774 if (value[0] == 0)
6775 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006776 if (xmlStrEqual(value, BAD_CAST "#all")) {
6777 if (flagAll != -1)
6778 *flags |= flagAll;
6779 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006780 if (flagExtension != -1)
6781 *flags |= flagExtension;
6782 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006783 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006784 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006785 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006786 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006787 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006788 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006789 *flags |= flagUnion;
6790 }
6791 } else {
6792 const xmlChar *end, *cur = value;
6793 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006794
Daniel Veillardc0826a72004-08-10 14:17:33 +00006795 do {
6796 while (IS_BLANK_CH(*cur))
6797 cur++;
6798 end = cur;
6799 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6800 end++;
6801 if (end == cur)
6802 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006803 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006804 if (xmlStrEqual(item, BAD_CAST "extension")) {
6805 if (flagExtension != -1) {
6806 if ((*flags & flagExtension) == 0)
6807 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006808 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006809 ret = 1;
6810 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6811 if (flagRestriction != -1) {
6812 if ((*flags & flagRestriction) == 0)
6813 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006814 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006815 ret = 1;
6816 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6817 if (flagSubstitution != -1) {
6818 if ((*flags & flagSubstitution) == 0)
6819 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006820 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006821 ret = 1;
6822 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6823 if (flagList != -1) {
6824 if ((*flags & flagList) == 0)
6825 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006826 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006827 ret = 1;
6828 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6829 if (flagUnion != -1) {
6830 if ((*flags & flagUnion) == 0)
6831 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006832 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006833 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006834 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006835 ret = 1;
6836 if (item != NULL)
6837 xmlFree(item);
6838 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006839 } while ((ret == 0) && (*cur != 0));
6840 }
6841
Daniel Veillardc0826a72004-08-10 14:17:33 +00006842 return (ret);
6843}
6844
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006845static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006846xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006847 xmlSchemaIDCPtr idc,
6848 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006849 xmlAttrPtr attr,
6850 int isField)
6851{
6852 xmlNodePtr node;
6853
6854 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006855 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006856 * Schema Component Constraint: Selector Value OK
6857 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006858 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006859 * in [XPath].
6860 */
6861 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006862 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006863 XML_SCHEMAP_INTERNAL,
6864 "Internal error: xmlSchemaCheckCSelectorXPath, "
6865 "the selector is not specified.\n", NULL, NULL);
6866 return (-1);
6867 }
6868 if (attr == NULL)
6869 node = idc->node;
6870 else
6871 node = (xmlNodePtr) attr;
6872 if (selector->xpath == NULL) {
6873 xmlSchemaPCustomErr(ctxt,
6874 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006875 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6876 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006877 "The XPath expression of the selector is not valid", NULL);
6878 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6879 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006880 const xmlChar **nsArray = NULL;
6881 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006882 /*
6883 * Compile the XPath expression.
6884 */
6885 /*
6886 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006887 * TODO: Call xmlPatterncompile with different options for selector/
6888 * field.
6889 */
6890 nsList = xmlGetNsList(attr->doc, attr->parent);
6891 /*
6892 * Build an array of prefixes and namespaces.
6893 */
6894 if (nsList != NULL) {
6895 int i, count = 0;
6896 xmlNsPtr ns;
6897
6898 for (i = 0; nsList[i] != NULL; i++)
6899 count++;
6900
6901 nsArray = (const xmlChar **) xmlMalloc(
6902 (count * 2 + 1) * sizeof(const xmlChar *));
6903 if (nsArray == NULL) {
6904 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6905 NULL);
6906 return (-1);
6907 }
6908 for (i = 0; i < count; i++) {
6909 ns = nsList[i];
6910 nsArray[2 * i] = nsList[i]->href;
6911 nsArray[2 * i + 1] = nsList[i]->prefix;
6912 }
6913 nsArray[count * 2] = NULL;
6914 xmlFree(nsList);
6915 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006916 /*
6917 * TODO: Differentiate between "selector" and "field".
6918 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006919 if (isField)
6920 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006921 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006922 else
6923 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006924 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006925 if (nsArray != NULL)
6926 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006927
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006928 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006929 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006930 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006931 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6932 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006933 "The XPath expression '%s' could not be "
6934 "compiled", selector->xpath);
6935 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006936 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006937 }
6938 return (0);
6939}
6940
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006941#define ADD_ANNOTATION(annot) \
6942 xmlSchemaAnnotPtr cur = item->annot; \
6943 if (item->annot == NULL) { \
6944 item->annot = annot; \
6945 return (annot); \
6946 } \
6947 cur = item->annot; \
6948 if (cur->next != NULL) { \
6949 cur = cur->next; \
6950 } \
6951 cur->next = annot;
6952
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006953/**
6954 * xmlSchemaAssignAnnotation:
6955 * @item: the schema component
6956 * @annot: the annotation
6957 *
6958 * Adds the annotation to the given schema component.
6959 *
6960 * Returns the given annotaion.
6961 */
6962static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006963xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6964 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006965{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006966 if ((annItem == NULL) || (annot == NULL))
6967 return (NULL);
6968 switch (annItem->type) {
6969 case XML_SCHEMA_TYPE_ELEMENT: {
6970 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6971 ADD_ANNOTATION(annot)
6972 }
6973 break;
6974 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6975 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6976 ADD_ANNOTATION(annot)
6977 }
6978 break;
6979 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6980 case XML_SCHEMA_TYPE_ANY: {
6981 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6982 ADD_ANNOTATION(annot)
6983 }
6984 break;
6985 case XML_SCHEMA_TYPE_PARTICLE:
6986 case XML_SCHEMA_TYPE_IDC_KEY:
6987 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006988 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006989 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6990 ADD_ANNOTATION(annot)
6991 }
6992 break;
6993 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
6994 xmlSchemaAttributeGroupPtr item =
6995 (xmlSchemaAttributeGroupPtr) annItem;
6996 ADD_ANNOTATION(annot)
6997 }
6998 break;
6999 case XML_SCHEMA_TYPE_NOTATION: {
7000 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7001 ADD_ANNOTATION(annot)
7002 }
7003 break;
7004 case XML_SCHEMA_FACET_MININCLUSIVE:
7005 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7006 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7007 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7008 case XML_SCHEMA_FACET_TOTALDIGITS:
7009 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7010 case XML_SCHEMA_FACET_PATTERN:
7011 case XML_SCHEMA_FACET_ENUMERATION:
7012 case XML_SCHEMA_FACET_WHITESPACE:
7013 case XML_SCHEMA_FACET_LENGTH:
7014 case XML_SCHEMA_FACET_MAXLENGTH:
7015 case XML_SCHEMA_FACET_MINLENGTH: {
7016 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7017 ADD_ANNOTATION(annot)
7018 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007019 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007020 case XML_SCHEMA_TYPE_SIMPLE:
7021 case XML_SCHEMA_TYPE_COMPLEX: {
7022 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7023 ADD_ANNOTATION(annot)
7024 }
7025 break;
7026 case XML_SCHEMA_TYPE_GROUP: {
7027 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7028 ADD_ANNOTATION(annot)
7029 }
7030 break;
7031 case XML_SCHEMA_TYPE_SEQUENCE:
7032 case XML_SCHEMA_TYPE_CHOICE:
7033 case XML_SCHEMA_TYPE_ALL: {
7034 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7035 ADD_ANNOTATION(annot)
7036 }
7037 break;
7038 default:
7039 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007040 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007041 NULL, NULL, NULL,
7042 "Internal error: xmlSchemaAddAnnotation, "
7043 "The item is not a annotated schema component", NULL);
7044 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007045 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007046 return (annot);
7047}
7048
7049/**
7050 * xmlSchemaParseIDCSelectorAndField:
7051 * @ctxt: a schema validation context
7052 * @schema: the schema being built
7053 * @node: a subtree containing XML Schema informations
7054 *
7055 * Parses a XML Schema identity-contraint definition's
7056 * <selector> and <field> elements.
7057 *
7058 * Returns the parsed identity-constraint definition.
7059 */
7060static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007061xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007062 xmlSchemaPtr schema,
7063 xmlSchemaIDCPtr idc,
7064 xmlNodePtr node,
7065 int isField)
7066{
7067 xmlSchemaIDCSelectPtr item;
7068 xmlNodePtr child = NULL;
7069 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007070
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007071 /*
7072 * Check for illegal attributes.
7073 */
7074 attr = node->properties;
7075 while (attr != NULL) {
7076 if (attr->ns == NULL) {
7077 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7078 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007079 xmlSchemaPIllegalAttrErr(ctxt,
7080 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7081 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007082 }
7083 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007084 xmlSchemaPIllegalAttrErr(ctxt,
7085 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7086 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007087 }
7088 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007089 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007090 /*
7091 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007092 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007093 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7094 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007095 xmlSchemaPErrMemory(ctxt,
7096 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007097 NULL);
7098 return (NULL);
7099 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007100 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007101 /*
7102 * Attribute "xpath" (mandatory).
7103 */
7104 attr = xmlSchemaGetPropNode(node, "xpath");
7105 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007106 xmlSchemaPMissingAttrErr(ctxt,
7107 XML_SCHEMAP_S4S_ATTR_MISSING,
7108 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007109 "name", NULL);
7110 } else {
7111 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7112 /*
7113 * URGENT TODO: "field"s have an other syntax than "selector"s.
7114 */
7115
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007116 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7117 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007118 xmlSchemaPErr(ctxt,
7119 (xmlNodePtr) attr,
7120 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007121 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007122 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007123 NULL, NULL);
7124 }
7125
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007126 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007127 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007128 /*
7129 * And now for the children...
7130 */
7131 child = node->children;
7132 if (IS_SCHEMA(child, "annotation")) {
7133 /*
7134 * Add the annotation to the parent IDC.
7135 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007136 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007137 xmlSchemaParseAnnotation(ctxt, schema, child));
7138 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007139 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007140 if (child != NULL) {
7141 xmlSchemaPContentErr(ctxt,
7142 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007143 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007144 NULL, "(annotation?)");
7145 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007146
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007147 return (item);
7148}
7149
7150/**
7151 * xmlSchemaParseIDC:
7152 * @ctxt: a schema validation context
7153 * @schema: the schema being built
7154 * @node: a subtree containing XML Schema informations
7155 *
7156 * Parses a XML Schema identity-contraint definition.
7157 *
7158 * Returns the parsed identity-constraint definition.
7159 */
7160static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007161xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007162 xmlSchemaPtr schema,
7163 xmlNodePtr node,
7164 xmlSchemaTypeType idcCategory,
7165 const xmlChar *targetNamespace)
7166{
7167 xmlSchemaIDCPtr item = NULL;
7168 xmlNodePtr child = NULL;
7169 xmlAttrPtr attr;
7170 const xmlChar *name = NULL;
7171 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7172 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007173
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007174 /*
7175 * Check for illegal attributes.
7176 */
7177 attr = node->properties;
7178 while (attr != NULL) {
7179 if (attr->ns == NULL) {
7180 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7181 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7182 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7183 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007184 xmlSchemaPIllegalAttrErr(ctxt,
7185 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7186 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007187 }
7188 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007189 xmlSchemaPIllegalAttrErr(ctxt,
7190 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7191 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007192 }
7193 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007194 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007195 /*
7196 * Attribute "name" (mandatory).
7197 */
7198 attr = xmlSchemaGetPropNode(node, "name");
7199 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007200 xmlSchemaPMissingAttrErr(ctxt,
7201 XML_SCHEMAP_S4S_ATTR_MISSING,
7202 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007203 "name", NULL);
7204 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007205 } else if (xmlSchemaPValAttrNode(ctxt,
7206 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007207 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7208 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007209 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007210 /*
7211 * Create the component.
7212 */
7213 if (schema->idcDef == NULL)
7214 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007215 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007216 return (NULL);
7217
7218 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7219 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007220 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007221 "allocating an identity-constraint definition", NULL);
7222 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007223 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007224 /*
7225 * Add the IDC to the list of IDCs on the schema component.
7226 */
7227 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007228 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007229 xmlSchemaPCustomErrExt(ctxt,
7230 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007231 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007232 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007233 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007234 name, targetNamespace, NULL);
7235 xmlFree(item);
7236 return (NULL);
7237 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007238 memset(item, 0, sizeof(xmlSchemaIDC));
7239 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007240 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007241 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007242 if (ctxt->assemble != NULL)
7243 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007244 /*
7245 * The target namespace of the parent element declaration.
7246 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007247 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007248 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7249 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007250 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7251 /*
7252 * Attribute "refer" (mandatory).
7253 */
7254 attr = xmlSchemaGetPropNode(node, "refer");
7255 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007256 xmlSchemaPMissingAttrErr(ctxt,
7257 XML_SCHEMAP_S4S_ATTR_MISSING,
7258 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007259 "refer", NULL);
7260 } else {
7261 /*
7262 * Create a reference item.
7263 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007264 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007265 NULL, NULL);
7266 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007267 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007268 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007269 NULL, NULL, attr,
7270 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007271 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007272 xmlSchemaCheckReference(ctxt, schema, node,
7273 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007274 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007275 }
7276 }
7277 /*
7278 * And now for the children...
7279 */
7280 child = node->children;
7281 if (IS_SCHEMA(child, "annotation")) {
7282 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7283 child = child->next;
7284 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007285 if (child == NULL) {
7286 xmlSchemaPContentErr(ctxt,
7287 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007288 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007289 "A child element is missing",
7290 "(annotation?, (selector, field+))");
7291 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007292 /*
7293 * Child element <selector>.
7294 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007295 if (IS_SCHEMA(child, "selector")) {
7296 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007297 item, child, 0);
7298 child = child->next;
7299 /*
7300 * Child elements <field>.
7301 */
7302 if (IS_SCHEMA(child, "field")) {
7303 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007304 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007305 item, child, 1);
7306 if (field != NULL) {
7307 field->index = item->nbFields;
7308 item->nbFields++;
7309 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007310 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007311 else
7312 item->fields = field;
7313 lastField = field;
7314 }
7315 child = child->next;
7316 } while (IS_SCHEMA(child, "field"));
7317 } else {
7318 xmlSchemaPContentErr(ctxt,
7319 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007320 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007321 NULL, "(annotation?, (selector, field+))");
7322 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007323 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007324 if (child != NULL) {
7325 xmlSchemaPContentErr(ctxt,
7326 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007327 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007328 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007329 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007330
7331 return (item);
7332}
7333
Daniel Veillardc0826a72004-08-10 14:17:33 +00007334/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007335 * xmlSchemaParseElement:
7336 * @ctxt: a schema validation context
7337 * @schema: the schema being built
7338 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007339 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007340 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007341 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007342 * *WARNING* this interface is highly subject to change
7343 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007344 * Returns the element declaration or a particle; NULL in case
7345 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007346 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007347static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007348xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007349 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007350{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007351 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007352 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007353 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007354 xmlNodePtr child = NULL;
7355 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007356 int min, max, isRef = 0;
7357 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007358
7359 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7360 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007361
Daniel Veillard4255d502002-04-16 15:50:10 +00007362 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007363 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007364 /*
7365 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007366 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007367 * robust.
7368 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007369 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007370 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007371 if ((topLevel) || (attr == NULL)) {
7372 if (nameAttr == NULL) {
7373 xmlSchemaPMissingAttrErr(ctxt,
7374 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007375 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007376 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007377 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007378 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007379 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007380
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007381 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007382 child = node->children;
7383 if (IS_SCHEMA(child, "annotation")) {
7384 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7385 child = child->next;
7386 }
7387 /*
7388 * Skip particle part if a global declaration.
7389 */
7390 if (topLevel)
7391 goto declaration_part;
7392 /*
7393 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007394 */
7395 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7396 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7397 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007398 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7399 if (particle == NULL)
7400 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007401
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007402 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7403
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007404 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007405 const xmlChar *refNs = NULL, *ref = NULL;
7406 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007407 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007408 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007409 */
7410 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007411 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007412 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007413 /*
7414 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007415 */
7416 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007417 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007418 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007419 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007420 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007421 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007422 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007423 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007424 attr = node->properties;
7425 while (attr != NULL) {
7426 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007427 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7428 xmlStrEqual(attr->name, BAD_CAST "name") ||
7429 xmlStrEqual(attr->name, BAD_CAST "id") ||
7430 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7431 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7432 {
7433 attr = attr->next;
7434 continue;
7435 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007436 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007437 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007438 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007439 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007440 "Only the attributes 'minOccurs', 'maxOccurs' and "
7441 "'id' are allowed in addition to 'ref'");
7442 break;
7443 }
7444 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7445 xmlSchemaPIllegalAttrErr(ctxt,
7446 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007447 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007448 }
7449 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007450 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007451 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007452 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007453 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007454 if (child != NULL) {
7455 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7456 NULL, NULL, node, child, NULL, "(annotation?)");
7457 }
7458 if ((min == 0) && (max == 0))
7459 goto return_null;
7460 /*
7461 * Create the reference item.
7462 */
7463 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7464 ref, refNs);
7465 if (refer == NULL)
7466 goto return_null;
7467 particle->children = (xmlSchemaTreeItemPtr) refer;
7468 particle->annot = annot;
7469 /*
7470 * Add to assembled items; the reference need to be resolved.
7471 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007472 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007473 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7474
7475 return ((xmlSchemaBasicItemPtr) particle);
7476 }
7477 /*
7478 * The declaration part ===============================================
7479 */
7480declaration_part:
7481 {
7482 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7483 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7484
7485 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007486 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007487 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007488 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007489 * Evaluate the target namespace.
7490 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007491 if (topLevel) {
7492 ns = schema->targetNamespace;
7493 } else {
7494 attr = xmlSchemaGetPropNode(node, "form");
7495 if (attr != NULL) {
7496 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7497 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007498 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007499 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007500 xmlSchemaPSimpleTypeErr(ctxt,
7501 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7502 NULL, (xmlNodePtr) attr,
7503 NULL, "(qualified | unqualified)",
7504 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007505 }
7506 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007507 ns = schema->targetNamespace;
7508 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007509 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007510 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007511 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007512 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007513 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7514 decl->node = node;
7515 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007516 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007517 * Check for illegal attributes.
7518 */
William M. Bracke7091952004-05-11 15:09:58 +00007519 attr = node->properties;
7520 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007521 if (attr->ns == NULL) {
7522 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7523 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007524 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007525 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007526 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007527 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007528 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7529 {
7530 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007531 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007532 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007533 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007534 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007535 xmlSchemaPIllegalAttrErr(ctxt,
7536 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7537 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007538 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007539 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7540 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007541 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7542
7543 xmlSchemaPIllegalAttrErr(ctxt,
7544 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007545 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007546 }
7547 }
7548 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007549
Daniel Veillardc0826a72004-08-10 14:17:33 +00007550 xmlSchemaPIllegalAttrErr(ctxt,
7551 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007552 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007553 }
7554 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007555 }
William M. Bracke7091952004-05-11 15:09:58 +00007556 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007557 * Extract/validate attributes.
7558 */
7559 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007560 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007561 * Process top attributes of global element declarations here.
7562 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007563 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7564 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007565 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7566 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7567 &(decl->substGroupNs), &(decl->substGroup));
7568 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007569 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007570 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007571 /*
7572 * Attribute "final".
7573 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007574 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007575 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007576 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7577 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7578 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7579 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007580 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007581 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7582 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007583 -1,
7584 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7585 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007586 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007587 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007588 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7589 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007590 attrValue, NULL, NULL, NULL);
7591 }
7592 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007593 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007594 /*
7595 * Attribute "block".
7596 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007597 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007598 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007599 /*
7600 * Apply default "block" values.
7601 */
7602 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7603 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7604 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7605 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7606 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7607 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007608 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007609 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7610 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007611 -1,
7612 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007613 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007614 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7615 xmlSchemaPSimpleTypeErr(ctxt,
7616 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007617 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007618 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007619 "restriction | substitution))", attrValue,
7620 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007621 }
7622 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007623 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007624 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007625 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007626
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007627 attr = xmlSchemaGetPropNode(node, "type");
7628 if (attr != NULL) {
7629 xmlSchemaPValAttrNodeQName(ctxt, schema,
7630 NULL, (xmlSchemaTypePtr) decl, attr,
7631 &(decl->namedTypeNs), &(decl->namedType));
7632 xmlSchemaCheckReference(ctxt, schema, node,
7633 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7634 }
7635 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7636 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007637 if (attr != NULL) {
7638 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007639 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007640 /*
7641 * 3.3.3 : 1
7642 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007643 */
7644 xmlSchemaPMutualExclAttrErr(ctxt,
7645 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007646 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007647 "default", "fixed");
7648 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007649 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7650 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007651 }
William M. Bracke7091952004-05-11 15:09:58 +00007652 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007653 /*
7654 * And now for the children...
7655 */
7656 oldcontainer = ctxt->container;
7657 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007658 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007659 /*
7660 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007661 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007662 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007663 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007664 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007665 xmlSchemaPContentErr(ctxt,
7666 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007667 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007668 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007669 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007670 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007671 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007672 child = child->next;
7673 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007674 /*
7675 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007676 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007677 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007678 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007679 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007680 xmlSchemaPContentErr(ctxt,
7681 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007682 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007683 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007684 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007685 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007686 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007687 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007688 }
William M. Bracke7091952004-05-11 15:09:58 +00007689 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007690 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007691 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007692 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007693 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007694 } else if (IS_SCHEMA(child, "key")) {
7695 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007696 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007697 } else if (IS_SCHEMA(child, "keyref")) {
7698 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007699 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007700 }
7701 if (lastIDC != NULL)
7702 lastIDC->next = curIDC;
7703 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007704 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007705 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007706 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007707 }
7708 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007709 xmlSchemaPContentErr(ctxt,
7710 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007711 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007712 NULL, "(annotation?, ((simpleType | complexType)?, "
7713 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007714 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007715 ctxt->container = oldcontainer;
7716 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007717 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007718 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007719 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007720 * different layer.
7721 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007722 FREE_AND_NULL(des)
7723 if (topLevel)
7724 return ((xmlSchemaBasicItemPtr) decl);
7725 else {
7726 particle->children = (xmlSchemaTreeItemPtr) decl;
7727 return ((xmlSchemaBasicItemPtr) particle);
7728 }
7729
7730return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007731 FREE_AND_NULL(des);
7732 if (annot != NULL) {
7733 if (particle != NULL)
7734 particle->annot = NULL;
7735 if (decl != NULL)
7736 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007737 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007738 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007739 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007740}
7741
7742/**
7743 * xmlSchemaParseUnion:
7744 * @ctxt: a schema validation context
7745 * @schema: the schema being built
7746 * @node: a subtree containing XML Schema informations
7747 *
7748 * parse a XML schema Union definition
7749 * *WARNING* this interface is highly subject to change
7750 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007751 * Returns -1 in case of internal error, 0 in case of success and a positive
7752 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007753 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007754static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007755xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007756 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007757{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007758 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007759 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007760 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007761 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007762
7763 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007764 return (-1);
7765 /* Not a component, don't create it. */
7766 type = ctxt->ctxtType;
7767 /*
7768 * Mark the simple type as being of variety "union".
7769 */
7770 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007771 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007772 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7773 * then the ·simple ur-type definition·."
7774 */
7775 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007776 /*
7777 * Check for illegal attributes.
7778 */
7779 attr = node->properties;
7780 while (attr != NULL) {
7781 if (attr->ns == NULL) {
7782 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7783 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007784 xmlSchemaPIllegalAttrErr(ctxt,
7785 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7786 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007787 }
7788 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007789 xmlSchemaPIllegalAttrErr(ctxt,
7790 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7791 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007792 }
7793 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007794 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007795 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007796 /*
7797 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007798 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007799 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007800 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007801 if (attr != NULL) {
7802 const xmlChar *end;
7803 xmlChar *tmp;
7804 const xmlChar *localName, *nsName;
7805 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7806 xmlSchemaQNameRefPtr ref;
7807
7808 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007809 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007810 do {
7811 while (IS_BLANK_CH(*cur))
7812 cur++;
7813 end = cur;
7814 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7815 end++;
7816 if (end == cur)
7817 break;
7818 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007819 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7820 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007821 /*
7822 * Create the member type link.
7823 */
7824 link = (xmlSchemaTypeLinkPtr)
7825 xmlMalloc(sizeof(xmlSchemaTypeLink));
7826 if (link == NULL) {
7827 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7828 "allocating a type link", NULL);
7829 return (-1);
7830 }
7831 link->type = NULL;
7832 link->next = NULL;
7833 if (lastLink == NULL)
7834 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007835 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007836 lastLink->next = link;
7837 lastLink = link;
7838 /*
7839 * Create a reference item.
7840 */
7841 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7842 localName, nsName);
7843 if (ref == NULL) {
7844 FREE_AND_NULL(tmp)
7845 return (-1);
7846 }
7847 /*
7848 * Assign the reference to the link, it will be resolved
7849 * later during fixup of the union simple type.
7850 */
7851 link->type = (xmlSchemaTypePtr) ref;
7852 }
7853 FREE_AND_NULL(tmp)
7854 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007855 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007856
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007857 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007858 /*
7859 * And now for the children...
7860 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007861 child = node->children;
7862 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007863 /*
7864 * Add the annotation to the simple type ancestor.
7865 */
7866 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7867 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007868 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007869 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007870 if (IS_SCHEMA(child, "simpleType")) {
7871 xmlSchemaTypePtr subtype, last = NULL;
7872
7873 /*
7874 * Anchor the member types in the "subtypes" field of the
7875 * simple type.
7876 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007877 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007878 subtype = (xmlSchemaTypePtr)
7879 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7880 if (subtype != NULL) {
7881 if (last == NULL) {
7882 type->subtypes = subtype;
7883 last = subtype;
7884 } else {
7885 last->next = subtype;
7886 last = subtype;
7887 }
7888 last->next = NULL;
7889 }
7890 child = child->next;
7891 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007892 }
7893 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007894 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007895 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007896 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007897 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007898 if ((attr == NULL) && (type->subtypes == NULL)) {
7899 /*
7900 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007901 * Either the memberTypes [attribute] of the <union> element must
7902 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007903 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007904 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007905 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7906 NULL, NULL, node,
7907 "Either the attribute 'memberTypes' or "
7908 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007909 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007910 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007911}
7912
7913/**
7914 * xmlSchemaParseList:
7915 * @ctxt: a schema validation context
7916 * @schema: the schema being built
7917 * @node: a subtree containing XML Schema informations
7918 *
7919 * parse a XML schema List definition
7920 * *WARNING* this interface is highly subject to change
7921 *
William M. Bracke7091952004-05-11 15:09:58 +00007922 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007923 * 1 in case of success.
7924 */
7925static xmlSchemaTypePtr
7926xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007927 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007928{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007929 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007930 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007931 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007932
7933 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7934 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007935 /* Not a component, don't create it. */
7936 type = ctxt->ctxtType;
7937 /*
7938 * Mark the type as being of variety "list".
7939 */
7940 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007941 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007942 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7943 * then the ·simple ur-type definition·."
7944 */
7945 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007946 /*
7947 * Check for illegal attributes.
7948 */
7949 attr = node->properties;
7950 while (attr != NULL) {
7951 if (attr->ns == NULL) {
7952 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7953 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007954 xmlSchemaPIllegalAttrErr(ctxt,
7955 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7956 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007957 }
7958 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007959 xmlSchemaPIllegalAttrErr(ctxt,
7960 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7961 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007962 }
7963 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007964 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007965
7966 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7967
William M. Brack2f2a6632004-08-20 23:09:47 +00007968 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007969 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7970 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007971 */
7972 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007973 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007974 /*
7975 * And now for the children...
7976 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007977 child = node->children;
7978 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007979 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7980 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007981 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007982 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007983 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007984 /*
7985 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007986 * Either the itemType [attribute] or the <simpleType> [child] of
7987 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007988 */
7989 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007990 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00007991 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007992 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00007993 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007994 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007995 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007996 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007997 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007998 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007999 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008000 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008001 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008002 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008003 "Either the attribute 'itemType' or the <simpleType> child "
8004 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008005 }
8006 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008007 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008008 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008009 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008010 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008011 if ((type->ref == NULL) &&
8012 (type->subtypes == NULL) &&
8013 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008014 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008015 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008016 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008017 "Either the attribute 'itemType' or the <simpleType> child "
8018 "must be present", NULL);
8019 }
8020 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008021}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008022
Daniel Veillard4255d502002-04-16 15:50:10 +00008023/**
8024 * xmlSchemaParseSimpleType:
8025 * @ctxt: a schema validation context
8026 * @schema: the schema being built
8027 * @node: a subtree containing XML Schema informations
8028 *
8029 * parse a XML schema Simple Type definition
8030 * *WARNING* this interface is highly subject to change
8031 *
William M. Bracke7091952004-05-11 15:09:58 +00008032 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008033 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008034 */
8035static xmlSchemaTypePtr
8036xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008037 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008038{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008039 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008040 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008041 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008042 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008043
8044 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8045 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008046
Daniel Veillardc0826a72004-08-10 14:17:33 +00008047 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008048 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008049 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008050 xmlSchemaPMissingAttrErr(ctxt,
8051 XML_SCHEMAP_S4S_ATTR_MISSING,
8052 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008053 "name", NULL);
8054 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008055 } else {
8056 if (xmlSchemaPValAttrNode(ctxt,
8057 NULL, NULL, attr,
8058 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8059 return (NULL);
8060 /*
8061 * Skip built-in types.
8062 */
8063 if (ctxt->isS4S) {
8064 xmlSchemaTypePtr biType;
8065
8066 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8067 if (biType != NULL)
8068 return (biType);
8069 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008070 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008071 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008072
Daniel Veillardc0826a72004-08-10 14:17:33 +00008073 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008074 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008075
Daniel Veillard01fa6152004-06-29 17:04:39 +00008076 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008077 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008078 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008079 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008080 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008081 if (type == NULL)
8082 return (NULL);
8083 type->node = node;
8084 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008085 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008086 /*
8087 * Check for illegal attributes.
8088 */
8089 attr = node->properties;
8090 while (attr != NULL) {
8091 if (attr->ns == NULL) {
8092 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008093 xmlSchemaPIllegalAttrErr(ctxt,
8094 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8095 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008096 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008097 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008098 xmlSchemaPIllegalAttrErr(ctxt,
8099 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8100 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008101 }
8102 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008103 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008104 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008105 /*
8106 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008107 *
8108 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008109 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008110 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008111 if (type == NULL)
8112 return (NULL);
8113 type->node = node;
8114 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008115 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008116 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8117 /*
8118 * Check for illegal attributes.
8119 */
8120 attr = node->properties;
8121 while (attr != NULL) {
8122 if (attr->ns == NULL) {
8123 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8124 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008125 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008126 xmlSchemaPIllegalAttrErr(ctxt,
8127 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8128 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008129 }
8130 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008131 xmlSchemaPIllegalAttrErr(ctxt,
8132 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8133 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008134 }
8135 attr = attr->next;
8136 }
8137 /*
8138 * Attribute "final".
8139 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008140 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008141 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008142 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8143 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8144 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8145 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8146 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8147 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008148 } else {
8149 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008150 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8151 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008152 XML_SCHEMAS_TYPE_FINAL_LIST,
8153 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8154
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008155 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008156 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008157 type, (xmlNodePtr) attr,
8158 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008159 attrValue, NULL, NULL, NULL);
8160 }
8161 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008162 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008163 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008164 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008165 /*
8166 * And now for the children...
8167 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008168 oldCtxtType = ctxt->ctxtType;
8169 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008170 ctxt->ctxtType = type;
8171 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008172 child = node->children;
8173 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008174 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8175 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008176 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008177 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008178 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8179 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008180 "(annotation?, (restriction | list | union))");
8181 } else if (IS_SCHEMA(child, "restriction")) {
8182 xmlSchemaParseRestriction(ctxt, schema, child,
8183 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008184 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008185 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008186 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008187 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008188 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008189 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008190 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008191 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008192 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008193 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8194 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008195 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008196 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008197 ctxt->parentItem = oldParentItem;
8198 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008199
Daniel Veillard4255d502002-04-16 15:50:10 +00008200 return (type);
8201}
8202
Daniel Veillard4255d502002-04-16 15:50:10 +00008203/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008204 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008205 * @ctxt: a schema validation context
8206 * @schema: the schema being built
8207 * @node: a subtree containing XML Schema informations
8208 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008209 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008210 * *WARNING* this interface is highly subject to change
8211 *
William M. Bracke7091952004-05-11 15:09:58 +00008212 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008213 * 1 in case of success.
8214 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008215static xmlSchemaTreeItemPtr
8216xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8217 xmlSchemaPtr schema,
8218 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008219{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008220 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008221 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008222 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008223 const xmlChar *ref = NULL, *refNs = NULL;
8224 int min, max;
8225
8226 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008227 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008228
8229 attr = xmlSchemaGetPropNode(node, "ref");
8230 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008231 xmlSchemaPMissingAttrErr(ctxt,
8232 XML_SCHEMAP_S4S_ATTR_MISSING,
8233 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008234 "ref", NULL);
8235 return (NULL);
8236 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008237 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008238 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008239 }
8240 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008241 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008242 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008243 /*
8244 * Check for illegal attributes.
8245 */
8246 attr = node->properties;
8247 while (attr != NULL) {
8248 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008249 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008250 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8251 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8252 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008253 xmlSchemaPIllegalAttrErr(ctxt,
8254 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8255 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008256 }
8257 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008258 xmlSchemaPIllegalAttrErr(ctxt,
8259 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8260 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008261 }
8262 attr = attr->next;
8263 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008264 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008265 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8266 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008267 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008268 /*
8269 * Create a reference item as the term; it will be substituted for
8270 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008271 */
8272 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008273 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8274 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8275 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8276 /*
8277 * And now for the children...
8278 */
8279 child = node->children;
8280 /* TODO: Is annotation even allowed for a model group reference? */
8281 if (IS_SCHEMA(child, "annotation")) {
8282 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008283 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008284 */
8285 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8286 child = child->next;
8287 }
8288 if (child != NULL) {
8289 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008290 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008291 NULL, NULL, node, child, NULL,
8292 "(annotation?)");
8293 }
8294 /*
8295 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8296 */
8297 if ((min == 0) && (max == 0))
8298 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008299 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008300 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8301 return ((xmlSchemaTreeItemPtr) item);
8302}
8303
8304/**
8305 * xmlSchemaParseModelGroupDefinition:
8306 * @ctxt: a schema validation context
8307 * @schema: the schema being built
8308 * @node: a subtree containing XML Schema informations
8309 *
8310 * Parses a XML schema model group definition.
8311 * *WARNING* this interface is highly subject to change
8312 *
8313 * Returns -1 in case of error, 0 if the declaration is improper and
8314 * 1 in case of success.
8315 */
8316static xmlSchemaModelGroupDefPtr
8317xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8318 xmlSchemaPtr schema,
8319 xmlNodePtr node)
8320{
8321 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008322 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008323 xmlAttrPtr attr;
8324 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008325
8326 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008327 return (NULL);
8328
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008329 attr = xmlSchemaGetPropNode(node, "name");
8330 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008331 xmlSchemaPMissingAttrErr(ctxt,
8332 XML_SCHEMAP_S4S_ATTR_MISSING,
8333 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008334 "name", NULL);
8335 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008336 } else if (xmlSchemaPValAttrNode(ctxt,
8337 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008338 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8339 return (NULL);
8340 }
8341 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8342 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008343 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008344 /*
8345 * Check for illegal attributes.
8346 */
8347 attr = node->properties;
8348 while (attr != NULL) {
8349 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008350 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008351 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008352 xmlSchemaPIllegalAttrErr(ctxt,
8353 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8354 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008355 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008356 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008357 xmlSchemaPIllegalAttrErr(ctxt,
8358 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8359 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008360 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008361 attr = attr->next;
8362 }
8363 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8364 /*
8365 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008366 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008367 child = node->children;
8368 if (IS_SCHEMA(child, "annotation")) {
8369 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8370 child = child->next;
8371 }
8372 if (IS_SCHEMA(child, "all")) {
8373 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8374 XML_SCHEMA_TYPE_ALL, 0);
8375 child = child->next;
8376 } else if (IS_SCHEMA(child, "choice")) {
8377 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8378 XML_SCHEMA_TYPE_CHOICE, 0);
8379 child = child->next;
8380 } else if (IS_SCHEMA(child, "sequence")) {
8381 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8382 XML_SCHEMA_TYPE_SEQUENCE, 0);
8383 child = child->next;
8384 }
8385 if (child != NULL) {
8386 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008387 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8388 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008389 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008390 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008391
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008392 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008393}
8394
8395/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008396 * xmlSchemaCleanupDoc:
8397 * @ctxt: a schema validation context
8398 * @node: the root of the document.
8399 *
8400 * removes unwanted nodes in a schemas document tree
8401 */
8402static void
8403xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8404{
8405 xmlNodePtr delete, cur;
8406
8407 if ((ctxt == NULL) || (root == NULL)) return;
8408
8409 /*
8410 * Remove all the blank text nodes
8411 */
8412 delete = NULL;
8413 cur = root;
8414 while (cur != NULL) {
8415 if (delete != NULL) {
8416 xmlUnlinkNode(delete);
8417 xmlFreeNode(delete);
8418 delete = NULL;
8419 }
8420 if (cur->type == XML_TEXT_NODE) {
8421 if (IS_BLANK_NODE(cur)) {
8422 if (xmlNodeGetSpacePreserve(cur) != 1) {
8423 delete = cur;
8424 }
8425 }
8426 } else if ((cur->type != XML_ELEMENT_NODE) &&
8427 (cur->type != XML_CDATA_SECTION_NODE)) {
8428 delete = cur;
8429 goto skip_children;
8430 }
8431
8432 /*
8433 * Skip to next node
8434 */
8435 if (cur->children != NULL) {
8436 if ((cur->children->type != XML_ENTITY_DECL) &&
8437 (cur->children->type != XML_ENTITY_REF_NODE) &&
8438 (cur->children->type != XML_ENTITY_NODE)) {
8439 cur = cur->children;
8440 continue;
8441 }
8442 }
8443 skip_children:
8444 if (cur->next != NULL) {
8445 cur = cur->next;
8446 continue;
8447 }
8448
8449 do {
8450 cur = cur->parent;
8451 if (cur == NULL)
8452 break;
8453 if (cur == root) {
8454 cur = NULL;
8455 break;
8456 }
8457 if (cur->next != NULL) {
8458 cur = cur->next;
8459 break;
8460 }
8461 } while (cur != NULL);
8462 }
8463 if (delete != NULL) {
8464 xmlUnlinkNode(delete);
8465 xmlFreeNode(delete);
8466 delete = NULL;
8467 }
8468}
8469
William M. Brack2f2a6632004-08-20 23:09:47 +00008470
8471/**
8472 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008473 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008474 * @ctxt: a schema validation context
8475 * @schemaLocation: an URI defining where to find the imported schema
8476 *
8477 * import a XML schema
8478 * *WARNING* this interface is highly subject to change
8479 *
8480 * Returns -1 in case of error and 1 in case of success.
8481 */
8482#if 0
8483static xmlSchemaImportPtr
8484xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8485 const xmlChar *schemaLocation)
8486{
8487 xmlSchemaImportPtr import;
8488 xmlSchemaParserCtxtPtr newctxt;
8489
8490 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8491 if (newctxt == NULL) {
8492 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8493 NULL);
8494 return (NULL);
8495 }
8496 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8497 /* Keep the same dictionnary for parsing, really */
8498 xmlDictReference(ctxt->dict);
8499 newctxt->dict = ctxt->dict;
8500 newctxt->includes = 0;
8501 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8502
8503 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8504 ctxt->userData);
8505
8506 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8507 if (import == NULL) {
8508 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8509 NULL);
8510 xmlSchemaFreeParserCtxt(newctxt);
8511 return (NULL);
8512 }
8513
8514 memset(import, 0, sizeof(xmlSchemaImport));
8515 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8516 import->schema = xmlSchemaParse(newctxt);
8517
8518 if (import->schema == NULL) {
8519 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008520 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008521 "Failed to import schema from location \"%s\".\n",
8522 schemaLocation, NULL);
8523
8524 xmlSchemaFreeParserCtxt(newctxt);
8525 /* The schemaLocation is held by the dictionary.
8526 if (import->schemaLocation != NULL)
8527 xmlFree((xmlChar *)import->schemaLocation);
8528 */
8529 xmlFree(import);
8530 return NULL;
8531 }
8532
8533 xmlSchemaFreeParserCtxt(newctxt);
8534 return import;
8535}
8536#endif
8537
8538static void
8539xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8540{
8541 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8542 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8543
8544 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8545 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8546
8547 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8548 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8549 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8550 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8551 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8552 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8553 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8554 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8555
8556 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8557 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8558 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8559 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8560 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8561 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8562}
8563
8564static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008565xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008566 xmlSchemaPtr schema,
8567 xmlNodePtr node)
8568{
8569 xmlAttrPtr attr;
8570 const xmlChar *val;
8571
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008572 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8573 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008574 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008575 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8576 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008577 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008578 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8579
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008580 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008581 if (attr != NULL) {
8582 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008583 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008584 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008585 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008586 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008587 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008588 "(qualified | unqualified)", val, NULL, NULL, NULL);
8589 }
8590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591
8592 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008593 if (attr != NULL) {
8594 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008595 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008596 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008597 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008598 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008599 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008600 "(qualified | unqualified)", val, NULL, NULL, NULL);
8601 }
8602 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603
8604 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008605 if (attr != NULL) {
8606 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8607 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8608 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8609 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8610 -1,
8611 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8612 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8613 xmlSchemaPSimpleTypeErr(ctxt,
8614 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008615 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008616 "(#all | List of (extension | restriction | list | union))",
8617 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008618 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008619 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008620
8621 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008622 if (attr != NULL) {
8623 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8624 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8625 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8626 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8627 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8628 xmlSchemaPSimpleTypeErr(ctxt,
8629 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008630 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008631 "(#all | List of (extension | restriction | substitution))",
8632 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008633 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008634 }
8635}
8636
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008637/**
8638 * xmlSchemaParseSchemaTopLevel:
8639 * @ctxt: a schema validation context
8640 * @schema: the schemas
8641 * @nodes: the list of top level nodes
8642 *
8643 * Returns the internal XML Schema structure built from the resource or
8644 * NULL in case of error
8645 */
8646static void
8647xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8648 xmlSchemaPtr schema, xmlNodePtr nodes)
8649{
8650 xmlNodePtr child;
8651 xmlSchemaAnnotPtr annot;
8652
8653 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8654 return;
8655
8656 child = nodes;
8657 while ((IS_SCHEMA(child, "include")) ||
8658 (IS_SCHEMA(child, "import")) ||
8659 (IS_SCHEMA(child, "redefine")) ||
8660 (IS_SCHEMA(child, "annotation"))) {
8661 if (IS_SCHEMA(child, "annotation")) {
8662 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8663 if (schema->annot == NULL)
8664 schema->annot = annot;
8665 else
8666 xmlSchemaFreeAnnot(annot);
8667 } else if (IS_SCHEMA(child, "import")) {
8668 xmlSchemaParseImport(ctxt, schema, child);
8669 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008670 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008671 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008672 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008673 } else if (IS_SCHEMA(child, "redefine")) {
8674 TODO
8675 }
8676 child = child->next;
8677 }
8678 while (child != NULL) {
8679 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008680 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008681 child = child->next;
8682 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008683 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008684 child = child->next;
8685 } else if (IS_SCHEMA(child, "element")) {
8686 xmlSchemaParseElement(ctxt, schema, child, 1);
8687 child = child->next;
8688 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008689 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008690 child = child->next;
8691 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008692 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008693 child = child->next;
8694 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008695 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008696 child = child->next;
8697 } else if (IS_SCHEMA(child, "notation")) {
8698 xmlSchemaParseNotation(ctxt, schema, child);
8699 child = child->next;
8700 } else {
8701 xmlSchemaPErr2(ctxt, NULL, child,
8702 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008703 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008704 child->name, NULL);
8705 child = child->next;
8706 }
8707 while (IS_SCHEMA(child, "annotation")) {
8708 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8709 if (schema->annot == NULL)
8710 schema->annot = annot;
8711 else
8712 xmlSchemaFreeAnnot(annot);
8713 child = child->next;
8714 }
8715 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008716 ctxt->parentItem = NULL;
8717 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008718}
8719
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008720static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008721xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008722 xmlHashTablePtr *imports,
8723 const xmlChar *nsName)
8724{
8725 xmlSchemaImportPtr ret;
8726
8727 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008728 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008729 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008730 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008731 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8732 NULL, NULL, (xmlNodePtr) ctxt->doc,
8733 "Internal error: failed to build the import table",
8734 NULL);
8735 return (NULL);
8736 }
8737 }
8738 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8739 if (ret == NULL) {
8740 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8741 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008742 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008743 memset(ret, 0, sizeof(xmlSchemaImport));
8744 if (nsName == NULL)
8745 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008746 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008747
8748 return (ret);
8749}
8750
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008751/**
8752 * xmlSchemaNewParserCtxtUseDict:
8753 * @URL: the location of the schema
8754 * @dict: the dictionary to be used
8755 *
8756 * Create an XML Schemas parse context for that file/resource expected
8757 * to contain an XML Schemas file.
8758 *
8759 * Returns the parser context or NULL in case of error
8760 */
8761static xmlSchemaParserCtxtPtr
8762xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8763{
8764 xmlSchemaParserCtxtPtr ret;
8765 /*
8766 if (URL == NULL)
8767 return (NULL);
8768 */
8769
8770 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8771 if (ret == NULL) {
8772 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8773 NULL);
8774 return (NULL);
8775 }
8776 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8777 ret->dict = dict;
8778 xmlDictReference(dict);
8779 if (URL != NULL)
8780 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8781 ret->includes = 0;
8782 return (ret);
8783}
8784
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008785static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008786xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8787{
8788 if (vctxt->pctxt == NULL) {
8789 if (vctxt->schema != NULL)
8790 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8791 else
8792 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8793 if (vctxt->pctxt == NULL) {
8794 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8795 "failed to create a temp. parser context");
8796 return (-1);
8797 }
8798 /* TODO: Pass user data. */
8799 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8800 }
8801 return (0);
8802}
8803
8804static int
8805xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008806 xmlSchemaPtr schema,
8807 xmlNodePtr node,
8808 const xmlChar *nsName,
8809 const xmlChar *location,
8810 xmlDocPtr *doc,
8811 const xmlChar **targetNamespace,
8812 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008813{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008814 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008815 xmlParserCtxtPtr parserCtxt;
8816 xmlSchemaImportPtr import;
8817 const xmlChar *ns;
8818 xmlNodePtr root;
8819
8820 /*
8821 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8822 * <xsi:noNamespaceSchemaLocation>.
8823 */
8824 *doc = NULL;
8825 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008826 * Given that the schemaLocation [attribute] is only a hint, it is open
8827 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008828 * namespace, regardless of the ·actual value· of schemaLocation, but
8829 * such a strategy risks missing useful information when new
8830 * schemaLocations are offered.
8831 *
8832 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8833 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8834 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008835 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008836 */
8837 if (location == NULL) {
8838 /*
8839 * Schema Document Location Strategy:
8840 *
8841 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008842 * either as a resource which is an XML document or a <schema> element
8843 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008844 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008845 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008846 *
8847 * NOTE: Those stategies are not supported, so we will skip.
8848 */
8849 return (0);
8850 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008851 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008852 ns = XML_SCHEMAS_NO_NAMESPACE;
8853 else
8854 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008855
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008856 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008857 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008858 /*
8859 * There was a valid resource for the specified namespace already
8860 * defined, so skip.
8861 * TODO: This might be changed someday to allow import of
8862 * components from multiple documents for a single target namespace.
8863 */
8864 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008865 }
8866 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8867 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8868 else {
8869 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8870 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8871 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008872 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008873 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008874 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008875 * 2 Based on the location URI, identify an existing schema document,
8876 * either as a resource which is an XML document or a <schema> element
8877 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008878 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008879 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008880 * web which is or contains or references a <schema> element;
8881 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8882 *
8883 */
8884 if ((absolute == 0) && (node != NULL)) {
8885 xmlChar *base, *URI;
8886
8887 base = xmlNodeGetBase(node->doc, node);
8888 if (base == NULL) {
8889 URI = xmlBuildURI(location, node->doc->URL);
8890 } else {
8891 URI = xmlBuildURI(location, base);
8892 xmlFree(base);
8893 }
8894 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008895 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008896 xmlFree(URI);
8897 }
8898 }
8899 parserCtxt = xmlNewParserCtxt();
8900 if (parserCtxt == NULL) {
8901 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8902 "allocating a parser context", NULL);
8903 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008904 }
8905 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008906 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008907 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008908 xmlDictReference(parserCtxt->dict);
8909 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008910 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008911 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008912 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008913 * 2.1 The referent is (a fragment of) a resource which is an
8914 * XML document (see clause 1.1), which in turn corresponds to
8915 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008916 * set, which in turn corresponds to a valid schema.
8917 * TODO: What to do with the "fragment" stuff?
8918 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008919 * 2.2 The referent is a <schema> element information item in
8920 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008921 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008922 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008923 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008924 */
8925 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008926 xmlErrorPtr lerr;
8927 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008928 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008929 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008930 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008931 * If the doc is NULL and the parser error is an IO error we
8932 * will assume that the resource could not be located or accessed.
8933 *
8934 * TODO: Try to find specific error codes to react only on
8935 * localisation failures.
8936 *
8937 * TODO, FIXME: Check the spec: is a namespace added to the imported
8938 * namespaces, even if the schemaLocation did not provide
8939 * a resource? I guess so, since omitting the "schemaLocation"
8940 * attribute, imports a namespace as well.
8941 */
8942 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008943 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008944 xmlFreeParserCtxt(parserCtxt);
8945 return(0);
8946 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008947 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008948 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008949 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008950 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008951 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008952 xmlFreeParserCtxt(parserCtxt);
8953 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8954 }
8955 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008956
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008957 root = xmlDocGetRootElement(*doc);
8958 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008961 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008962 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008963 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008964 xmlFreeDoc(*doc);
8965 *doc = NULL;
8966 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 }
8968
8969 xmlSchemaCleanupDoc(pctxt, root);
8970
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008971 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008972 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008973 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008974 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008975 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008976 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008977 xmlFreeDoc(*doc);
8978 *doc = NULL;
8979 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008980 }
8981 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008982 /*
8983 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008984 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985 if (nsName == NULL) {
8986 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008987 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008988 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008989 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008990 "The XML schema to be imported is not expected "
8991 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 xmlFreeDoc(*doc);
8994 *doc = NULL;
8995 return (XML_SCHEMAP_SRC_IMPORT_3_2);
8996 }
8997 } else {
8998 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008999 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009000 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009001 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009002 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009003 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009004 xmlFreeDoc(*doc);
9005 *doc = NULL;
9006 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9007 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009008 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009009 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009010 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009011 "The XML schema to be imported is expected to have a "
9012 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009013 "its target namespace of '%s'",
9014 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009015 xmlFreeDoc(*doc);
9016 *doc = NULL;
9017 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9018 }
9019 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009020 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009021 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009022 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9023 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009024 xmlFreeDoc(*doc);
9025 *doc = NULL;
9026 return (-1);
9027 }
9028 import->schemaLocation = location;
9029 import->doc = *doc;
9030 return (0);
9031}
William M. Brack2f2a6632004-08-20 23:09:47 +00009032
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009033static void
9034xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9035 xmlSchemaPtr schema,
9036 const xmlChar *targetNamespace,
9037 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009038{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009039 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009040 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009041
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009042 /*
9043 * Save and reset the context & schema.
9044 */
9045 oldURL = pctxt->URL;
9046 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009047 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009048 oldLocImps = pctxt->localImports;
9049 pctxt->localImports = NULL;
9050 oldNumLocImps = pctxt->nbLocalImports;
9051 pctxt->nbLocalImports = 0;
9052 oldSizeLocImps = pctxt->sizeLocalImports;
9053 pctxt->sizeLocalImports = 0;
9054 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009055 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009056 xmlSchemaClearSchemaDefaults(schema);
9057 oldTNS = schema->targetNamespace;
9058 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009059 if ((targetNamespace != NULL) &&
9060 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9061 /*
9062 * We are parsing the schema for schema!
9063 */
9064 pctxt->isS4S = 1;
9065 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009066 /*
9067 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009068 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009069 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9070 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9071 /*
9072 * Restore the context & schema.
9073 */
9074 schema->flags = oldFlags;
9075 schema->targetNamespace = oldTNS;
9076 if (pctxt->localImports != NULL)
9077 xmlFree((xmlChar *) pctxt->localImports);
9078 pctxt->localImports = oldLocImps;
9079 pctxt->nbLocalImports = oldNumLocImps;
9080 pctxt->sizeLocalImports = oldSizeLocImps;
9081 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009082 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009083}
9084
William M. Brack2f2a6632004-08-20 23:09:47 +00009085/**
9086 * xmlSchemaParseImport:
9087 * @ctxt: a schema validation context
9088 * @schema: the schema being built
9089 * @node: a subtree containing XML Schema informations
9090 *
9091 * parse a XML schema Import definition
9092 * *WARNING* this interface is highly subject to change
9093 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009094 * Returns 0 in case of success, a positive error code if
9095 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009096 */
9097static int
9098xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9099 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009100{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009101 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009102 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009103 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009104 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009105 xmlAttrPtr attr;
9106 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009107 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009108
9109 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9110 return (-1);
9111
9112 /*
9113 * Check for illegal attributes.
9114 */
9115 attr = node->properties;
9116 while (attr != NULL) {
9117 if (attr->ns == NULL) {
9118 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9119 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9120 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009121 xmlSchemaPIllegalAttrErr(ctxt,
9122 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9123 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009124 }
9125 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009126 xmlSchemaPIllegalAttrErr(ctxt,
9127 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9128 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009129 }
9130 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009131 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009132 /*
9133 * Extract and validate attributes.
9134 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009135 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9136 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009137 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009138 xmlSchemaPSimpleTypeErr(ctxt,
9139 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9140 NULL, node,
9141 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009142 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009143 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9144 }
9145
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009146 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9147 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009148 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009149 xmlSchemaPSimpleTypeErr(ctxt,
9150 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9151 NULL, node,
9152 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009153 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009154 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009155 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009156 /*
9157 * And now for the children...
9158 */
9159 child = node->children;
9160 if (IS_SCHEMA(child, "annotation")) {
9161 /*
9162 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009163 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009164 */
9165 child = child->next;
9166 }
9167 if (child != NULL) {
9168 xmlSchemaPContentErr(ctxt,
9169 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9170 NULL, NULL, node, child, NULL,
9171 "(annotation?)");
9172 }
9173 /*
9174 * Apply additional constraints.
9175 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009176 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009177 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009178 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9179 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009180 * targetNamespace [attribute].
9181 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009182 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009183 xmlSchemaPCustomErr(ctxt,
9184 XML_SCHEMAP_SRC_IMPORT_1_1,
9185 NULL, NULL, node,
9186 "The value of the attribute 'namespace' must not match "
9187 "the target namespace '%s' of the importing schema",
9188 schema->targetNamespace);
9189 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9190 }
9191 } else {
9192 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009193 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009194 * <schema> must have a targetNamespace [attribute].
9195 */
9196 if (schema->targetNamespace == NULL) {
9197 xmlSchemaPCustomErr(ctxt,
9198 XML_SCHEMAP_SRC_IMPORT_1_2,
9199 NULL, NULL, node,
9200 "The attribute 'namespace' must be existent if "
9201 "the importing schema has no target namespace",
9202 NULL);
9203 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9204 }
9205 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009206 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009207 * Add the namespace to the list of locally imported namespace.
9208 */
9209 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009210 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009211 sizeof(const xmlChar*));
9212 ctxt->sizeLocalImports = 10;
9213 ctxt->nbLocalImports = 0;
9214 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9215 ctxt->sizeLocalImports *= 2;
9216 ctxt->localImports = (const xmlChar **) xmlRealloc(
9217 (xmlChar **) ctxt->localImports,
9218 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9219 }
9220 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9221 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009222 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009223 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009224 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9225 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009226 schemaLocation, &doc, &targetNamespace, 0);
9227 if (ret != 0) {
9228 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009229 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009230 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009231 } else if (doc != NULL) {
9232 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9233 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009234 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009235
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009236 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009237}
9238
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009239/**
9240 * xmlSchemaParseInclude:
9241 * @ctxt: a schema validation context
9242 * @schema: the schema being built
9243 * @node: a subtree containing XML Schema informations
9244 *
9245 * parse a XML schema Include definition
9246 *
William M. Bracke7091952004-05-11 15:09:58 +00009247 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009248 * 1 in case of success.
9249 */
9250static int
9251xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9252 xmlNodePtr node)
9253{
9254 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009255 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009256 xmlDocPtr doc = NULL;
9257 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009258 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009259 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009260 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009261 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009262
9263
9264 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9265 return (-1);
9266
9267 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009268 * Check for illegal attributes.
9269 */
9270 attr = node->properties;
9271 while (attr != NULL) {
9272 if (attr->ns == NULL) {
9273 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9274 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009275 xmlSchemaPIllegalAttrErr(ctxt,
9276 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9277 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009278 }
9279 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009280 xmlSchemaPIllegalAttrErr(ctxt,
9281 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9282 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009283 }
9284 attr = attr->next;
9285 }
9286 /*
9287 * Extract and validate attributes.
9288 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009289 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009290 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009291 * Preliminary step, extract the URI-Reference for the include and
9292 * make an URI from the base.
9293 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009294 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9295 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009296 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009297 xmlChar *uri = NULL;
9298
9299 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9300 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009301 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009302 base = xmlNodeGetBase(node->doc, node);
9303 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009304 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009305 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009306 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009307 xmlFree(base);
9308 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009309 if (uri == NULL) {
9310 xmlSchemaPErr(ctxt,
9311 node,
9312 XML_SCHEMAP_INTERNAL,
9313 "Internal error: xmlSchemaParseInclude, "
9314 "could not build an URI from the schemaLocation.\n",
9315 NULL, NULL);
9316 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009317 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009318 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9319 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009320 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009321 xmlSchemaPMissingAttrErr(ctxt,
9322 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9323 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009324 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009325 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009326 /*
9327 * And now for the children...
9328 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009329 child = node->children;
9330 while (IS_SCHEMA(child, "annotation")) {
9331 /*
9332 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009333 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009334 */
9335 child = child->next;
9336 }
9337 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009338 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009339 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9340 NULL, NULL, node, child, NULL,
9341 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009342 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009343 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009344 * Report self-inclusion.
9345 */
9346 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9347 xmlSchemaPCustomErr(ctxt,
9348 XML_SCHEMAP_SRC_INCLUDE,
9349 NULL, NULL, node,
9350 "The schema document '%s' cannot include itself.",
9351 schemaLocation);
9352 return (XML_SCHEMAP_SRC_INCLUDE);
9353 }
9354 /*
9355 * Check if this one was already processed to avoid incorrect
9356 * duplicate component errors and infinite circular inclusion.
9357 */
9358 include = schema->includes;
9359 while (include != NULL) {
9360 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9361 targetNamespace = include->origTargetNamespace;
9362 if (targetNamespace == NULL) {
9363 /*
9364 * Chameleon include: skip only if it was build for
9365 * the targetNamespace of the including schema.
9366 */
9367 if (xmlStrEqual(schema->targetNamespace,
9368 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009369 goto check_targetNamespace;
9370 }
9371 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009372 goto check_targetNamespace;
9373 }
9374 }
9375 include = include->next;
9376 }
9377 /*
9378 * First step is to parse the input document into an DOM/Infoset
9379 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009380 */
9381 parserCtxt = xmlNewParserCtxt();
9382 if (parserCtxt == NULL) {
9383 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9384 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009385 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009386 }
9387
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009388 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9389 xmlDictFree(parserCtxt->dict);
9390 parserCtxt->dict = ctxt->dict;
9391 xmlDictReference(parserCtxt->dict);
9392 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009393
9394 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009395 NULL, SCHEMAS_PARSE_OPTIONS);
9396 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009397 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009398 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009399 * TODO: It is not an error for the ·actual value· of the
9400 * schemaLocation [attribute] to fail to resolve it all, in which
9401 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009402 * So do we need a warning report here?
9403 */
9404 xmlSchemaPCustomErr(ctxt,
9405 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009406 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009407 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009408 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009409 }
9410
9411 /*
9412 * Then extract the root of the schema
9413 */
9414 root = xmlDocGetRootElement(doc);
9415 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009416 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009417 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009418 NULL, NULL, node,
9419 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009420 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009421 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009422 }
9423
9424 /*
9425 * Remove all the blank text nodes
9426 */
9427 xmlSchemaCleanupDoc(ctxt, root);
9428
9429 /*
9430 * Check the schemas top level element
9431 */
9432 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009433 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009434 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009435 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009436 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009437 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009438 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009439 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009440
William M. Brack2f2a6632004-08-20 23:09:47 +00009441 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009442 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009443 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9444 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009445 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9446 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009447check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009448 if (targetNamespace != NULL) {
9449 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009450 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009451 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009452 NULL, NULL, node,
9453 "The target namespace of the included schema "
9454 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009455 "has no target namespace",
9456 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009457 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009458 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9459 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009460 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009461 NULL, NULL, node,
9462 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009463 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009464 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009465 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009466 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009467 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009468 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009469 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009470 } else
9471 wasConvertingNs = 1;
9472 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009473
9474 if (include != NULL)
9475 goto exit;
9476
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009477 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009478 * URGENT TODO: If the schema is a chameleon-include then copy the
9479 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009480 * of those components, do nothing otherwise.
9481 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009482 * for every destinct including targetNamespace; thus not performant at
9483 * the moment.
9484 * TODO: Check when the namespace in wildcards for chameleons needs
9485 * to be converted: before we built wildcard intersections or after.
9486 */
9487 /*
9488 * Register the include.
9489 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009490 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9491 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009492 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9493 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009494 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009495 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009496 include->next = schema->includes;
9497 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009498 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009499 * TODO: Use the resolved URI for the this location, since it might
9500 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009501 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009502 include->schemaLocation = schemaLocation;
9503 include->doc = doc;
9504 /*
9505 * In case of chameleons, the original target namespace will differ
9506 * from the resulting namespace.
9507 */
9508 include->origTargetNamespace = targetNamespace;
9509 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009510#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009511 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009512 xmlGenericError(xmlGenericErrorContext,
9513 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9514 " into TNS '%s'\n", schemaLocation,
9515 targetNamespace, schema->targetNamespace);
9516 else
9517 xmlGenericError(xmlGenericErrorContext,
9518 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9519 targetNamespace);
9520#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009521 /*
9522 * Compile the included schema.
9523 */
9524 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9525
9526exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009527 /*
9528 * Remove the converting flag.
9529 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009530 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009531 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009532 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009533 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009534
9535exit_invalid:
9536 if (doc != NULL) {
9537 if (include != NULL)
9538 include->doc = NULL;
9539 xmlFreeDoc(doc);
9540 }
9541 return (ctxt->err);
9542
9543exit_failure:
9544 if (doc != NULL) {
9545 if (include != NULL)
9546 include->doc = NULL;
9547 xmlFreeDoc(doc);
9548 }
9549 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009550}
9551
9552/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009553 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009554 * @ctxt: a schema validation context
9555 * @schema: the schema being built
9556 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009557 * @type: the "compositor" type
9558 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009559 *
9560 * parse a XML schema Sequence definition
9561 * *WARNING* this interface is highly subject to change
9562 *
William M. Bracke7091952004-05-11 15:09:58 +00009563 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009564 * 1 in case of success.
9565 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009566static xmlSchemaTreeItemPtr
9567xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9568 xmlNodePtr node, xmlSchemaTypeType type,
9569 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009570{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009571 xmlSchemaModelGroupPtr item;
9572 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009573 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009574 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009575 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009576 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009577
9578 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009579 return (NULL);
9580 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009581 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009582 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009583 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9584 if (item == NULL)
9585 return (NULL);
9586
9587 if (withParticle) {
9588 if (type == XML_SCHEMA_TYPE_ALL) {
9589 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009590 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009591 } else {
9592 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009593 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9594 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9595 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009596 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009597 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9598 /*
9599 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009600 */
9601 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9602 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009603 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009604 particle->children = (xmlSchemaTreeItemPtr) item;
9605 /*
9606 * Check for illegal attributes.
9607 */
9608 attr = node->properties;
9609 while (attr != NULL) {
9610 if (attr->ns == NULL) {
9611 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9612 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9613 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009614 xmlSchemaPIllegalAttrErr(ctxt,
9615 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9616 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009617 }
9618 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009619 xmlSchemaPIllegalAttrErr(ctxt,
9620 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9621 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009622 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009623 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009624 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009625 } else {
9626 /*
9627 * Check for illegal attributes.
9628 */
9629 attr = node->properties;
9630 while (attr != NULL) {
9631 if (attr->ns == NULL) {
9632 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
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);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009641 }
9642 attr = attr->next;
9643 }
9644
William M. Brack2f2a6632004-08-20 23:09:47 +00009645 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009646
William M. Brack2f2a6632004-08-20 23:09:47 +00009647 /*
9648 * Extract and validate attributes.
9649 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009650 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009651 /*
9652 * And now for the children...
9653 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009654 child = node->children;
9655 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009656 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009657 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009658 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009659 oldcontainer = ctxt->container;
9660 ctxt->container = container;
9661 if (type == XML_SCHEMA_TYPE_ALL) {
9662 xmlSchemaParticlePtr part, last = NULL;
9663
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009664 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009665 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9666 schema, child, 0);
9667 if (part != NULL) {
9668 if (part->minOccurs > 1)
9669 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009670 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009671 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9672 if (part->maxOccurs > 1)
9673 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009674 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009675 "Invalid value for maxOccurs (must be 0 or 1)",
9676 NULL);
9677 if (last == NULL)
9678 item->children = (xmlSchemaTreeItemPtr) part;
9679 else
9680 last->next = (xmlSchemaTreeItemPtr) part;
9681 last = part;
9682 }
9683 child = child->next;
9684 }
9685 if (child != NULL) {
9686 xmlSchemaPContentErr(ctxt,
9687 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9688 NULL, NULL, node, child, NULL,
9689 "(annotation?, (annotation?, element*)");
9690 }
9691 } else {
9692 /* choice + sequence */
9693 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9694
9695 while ((IS_SCHEMA(child, "element")) ||
9696 (IS_SCHEMA(child, "group")) ||
9697 (IS_SCHEMA(child, "any")) ||
9698 (IS_SCHEMA(child, "choice")) ||
9699 (IS_SCHEMA(child, "sequence"))) {
9700
9701 if (IS_SCHEMA(child, "element")) {
9702 part = (xmlSchemaTreeItemPtr)
9703 xmlSchemaParseElement(ctxt, schema, child, 0);
9704 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009705 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009706 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9707 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009708 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009709 xmlSchemaParseAny(ctxt, schema, child);
9710 } else if (IS_SCHEMA(child, "choice")) {
9711 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9712 XML_SCHEMA_TYPE_CHOICE, 1);
9713 } else if (IS_SCHEMA(child, "sequence")) {
9714 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9715 XML_SCHEMA_TYPE_SEQUENCE, 1);
9716 }
9717 if (part != NULL) {
9718 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009719 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009720 else
9721 last->next = part;
9722 last = part;
9723 }
9724 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009725 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009726 if (child != NULL) {
9727 xmlSchemaPContentErr(ctxt,
9728 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9729 NULL, NULL, node, child, NULL,
9730 "(annotation?, (element | group | choice | sequence | any)*)");
9731 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009732 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009733 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009734 if (withParticle) {
9735 if ((min == 0) && (max == 0))
9736 return (NULL);
9737 else
9738 return ((xmlSchemaTreeItemPtr) particle);
9739 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009740 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009741}
9742
9743/**
9744 * xmlSchemaParseRestriction:
9745 * @ctxt: a schema validation context
9746 * @schema: the schema being built
9747 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009748 *
9749 * parse a XML schema Restriction definition
9750 * *WARNING* this interface is highly subject to change
9751 *
9752 * Returns the type definition or NULL in case of error
9753 */
9754static xmlSchemaTypePtr
9755xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009756 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009757{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009758 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009759 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009760 char buf[30];
9761 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009762 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009763
9764 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9765 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009766 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009767 type = ctxt->ctxtType;
9768 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009769
9770 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009771 * TODO: Is the container needed at all? the anonymous
9772 * items inside should generate unique names already.
9773 */
9774 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009775 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009776 /*
9777 * Check for illegal attributes.
9778 */
9779 attr = node->properties;
9780 while (attr != NULL) {
9781 if (attr->ns == NULL) {
9782 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9783 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009784 xmlSchemaPIllegalAttrErr(ctxt,
9785 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9786 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009787 }
9788 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009789 xmlSchemaPIllegalAttrErr(ctxt,
9790 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9791 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009792 }
9793 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009794 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009795 /*
9796 * Extract and validate attributes.
9797 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009798 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009799 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009800 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009801 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009802 /*
9803 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9804 * among its [children]), the simple type definition which is
9805 * the {content type} of the type definition ·resolved· to by
9806 * the ·actual value· of the base [attribute]"
9807 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009808 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009809 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009810 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009811 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009812 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009813 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009814 XML_SCHEMAP_S4S_ATTR_MISSING,
9815 type, node, "base", NULL);
9816 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009817 /*
9818 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009819 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009820 child = node->children;
9821 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009822 /*
9823 * Add the annotation to the simple type ancestor.
9824 */
9825 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9826 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009827 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009828 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009829 oldcontainer = ctxt->container;
9830 ctxt->container = container;
9831 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9832 /*
9833 * Corresponds to <simpleType><restriction><simpleType>.
9834 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009835 if (IS_SCHEMA(child, "simpleType")) {
9836 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009837 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009838 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009839 * Either the base [attribute] or the simpleType [child] of the
9840 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009841 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009842 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009843 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009844 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009845 "The attribute 'base' and the <simpleType> child are "
9846 "mutually exclusive", NULL);
9847 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009848 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009849 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009850 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009851 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009852 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009853 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009854 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9855 NULL, NULL, node, child,
9856 "Either the attribute 'base' or a <simpleType> child "
9857 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009858 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009859 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9860 /*
9861 * Corresponds to <complexType><complexContent><restriction>...
9862 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009863 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009864 * Model groups <all>, <choice> and <sequence>.
9865 */
9866 if (IS_SCHEMA(child, "all")) {
9867 type->subtypes = (xmlSchemaTypePtr)
9868 xmlSchemaParseModelGroup(ctxt, schema, child,
9869 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009870 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009871 } else if (IS_SCHEMA(child, "choice")) {
9872 type->subtypes = (xmlSchemaTypePtr)
9873 xmlSchemaParseModelGroup(ctxt,
9874 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9875 child = child->next;
9876 } else if (IS_SCHEMA(child, "sequence")) {
9877 type->subtypes = (xmlSchemaTypePtr)
9878 xmlSchemaParseModelGroup(ctxt, schema, child,
9879 XML_SCHEMA_TYPE_SEQUENCE, 1);
9880 child = child->next;
9881 /*
9882 * Model group reference <group>.
9883 */
9884 } else if (IS_SCHEMA(child, "group")) {
9885 type->subtypes = (xmlSchemaTypePtr)
9886 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9887 child = child->next;
9888 }
9889 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009890 /*
9891 * Corresponds to <complexType><simpleContent><restriction>...
9892 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009893 * "1.1 the simple type definition corresponding to the <simpleType>
9894 * among the [children] of <restriction> if there is one;"
9895 */
9896 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009897 /*
9898 * We will store the to-be-restricted simple type in
9899 * type->contentTypeDef *temporarily*.
9900 */
9901 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009902 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009903 if ( type->contentTypeDef == NULL)
9904 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009905 child = child->next;
9906 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009907 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009908
9909 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009910 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009911 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009912 /*
9913 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009914 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009915 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009916
Daniel Veillard01fa6152004-06-29 17:04:39 +00009917 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009918 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009919 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009920 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009921 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9922 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009923 * *Single Facet Value*
9924 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009925 while ((IS_SCHEMA(child, "minInclusive")) ||
9926 (IS_SCHEMA(child, "minExclusive")) ||
9927 (IS_SCHEMA(child, "maxInclusive")) ||
9928 (IS_SCHEMA(child, "maxExclusive")) ||
9929 (IS_SCHEMA(child, "totalDigits")) ||
9930 (IS_SCHEMA(child, "fractionDigits")) ||
9931 (IS_SCHEMA(child, "pattern")) ||
9932 (IS_SCHEMA(child, "enumeration")) ||
9933 (IS_SCHEMA(child, "whiteSpace")) ||
9934 (IS_SCHEMA(child, "length")) ||
9935 (IS_SCHEMA(child, "maxLength")) ||
9936 (IS_SCHEMA(child, "minLength"))) {
9937 facet = xmlSchemaParseFacet(ctxt, schema, child);
9938 if (facet != NULL) {
9939 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009940 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009941 else
9942 lastfacet->next = facet;
9943 lastfacet = facet;
9944 lastfacet->next = NULL;
9945 }
9946 child = child->next;
9947 }
9948 /*
9949 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009950 */
9951 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009952 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9953
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009954 facet = type->facets;
9955 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009956 facetLink = (xmlSchemaFacetLinkPtr)
9957 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009958 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009959 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009960 xmlFree(facetLink);
9961 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009962 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009963 facetLink->facet = facet;
9964 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009965 if (lastFacetLink == NULL)
9966 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009967 else
9968 lastFacetLink->next = facetLink;
9969 lastFacetLink = facetLink;
9970 facet = facet->next;
9971 } while (facet != NULL);
9972 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009973 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009974 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9975 /*
9976 * Attribute uses/declarations.
9977 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009978 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009979 /*
9980 * Attribute wildcard.
9981 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009982 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009983 type->attributeWildcard =
9984 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009985 child = child->next;
9986 }
9987 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009988 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009989 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9990 xmlSchemaPContentErr(ctxt,
9991 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009992 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009993 "annotation?, (group | all | choice | sequence)?, "
9994 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009995 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009996 xmlSchemaPContentErr(ctxt,
9997 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009998 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00009999 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10000 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10001 "length | minLength | maxLength | enumeration | whiteSpace | "
10002 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10003 } else {
10004 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010005 xmlSchemaPContentErr(ctxt,
10006 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010007 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010008 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10009 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10010 "length | minLength | maxLength | enumeration | whiteSpace | "
10011 "pattern)*))");
10012 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010013 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010014 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010015 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010016}
10017
10018/**
10019 * xmlSchemaParseExtension:
10020 * @ctxt: a schema validation context
10021 * @schema: the schema being built
10022 * @node: a subtree containing XML Schema informations
10023 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010024 * Parses an <extension>, which is found inside a
10025 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010026 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010027 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010028 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010029 */
10030static xmlSchemaTypePtr
10031xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010032 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010033{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010034 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010035 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010036 char buf[30];
10037 const xmlChar *oldcontainer, *container;
10038 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010039
10040 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10041 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010042 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010043 type = ctxt->ctxtType;
10044 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010045
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010046 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10047 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10048 /*
10049 * Check for illegal attributes.
10050 */
10051 attr = node->properties;
10052 while (attr != NULL) {
10053 if (attr->ns == NULL) {
10054 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10055 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010056 xmlSchemaPIllegalAttrErr(ctxt,
10057 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10058 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010059 }
10060 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010061 xmlSchemaPIllegalAttrErr(ctxt,
10062 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10063 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010064 }
10065 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010066 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010067
10068 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010069
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010070 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010071 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010072 */
10073 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010074 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10075 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010076 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010077 XML_SCHEMAP_S4S_ATTR_MISSING,
10078 NULL, node, "base", NULL);
10079 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010080 /*
10081 * And now for the children...
10082 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010083 child = node->children;
10084 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010085 /*
10086 * Add the annotation to the type ancestor.
10087 */
10088 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10089 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010090 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010091 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010092 oldcontainer = ctxt->container;
10093 ctxt->container = container;
10094 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10095 /*
10096 * Corresponds to <complexType><complexContent><extension>... and:
10097 *
10098 * Model groups <all>, <choice>, <sequence> and <group>.
10099 */
10100 if (IS_SCHEMA(child, "all")) {
10101 type->subtypes = (xmlSchemaTypePtr)
10102 xmlSchemaParseModelGroup(ctxt, schema,
10103 child, XML_SCHEMA_TYPE_ALL, 1);
10104 child = child->next;
10105 } else if (IS_SCHEMA(child, "choice")) {
10106 type->subtypes = (xmlSchemaTypePtr)
10107 xmlSchemaParseModelGroup(ctxt, schema,
10108 child, XML_SCHEMA_TYPE_CHOICE, 1);
10109 child = child->next;
10110 } else if (IS_SCHEMA(child, "sequence")) {
10111 type->subtypes = (xmlSchemaTypePtr)
10112 xmlSchemaParseModelGroup(ctxt, schema,
10113 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10114 child = child->next;
10115 } else if (IS_SCHEMA(child, "group")) {
10116 type->subtypes = (xmlSchemaTypePtr)
10117 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10118 child = child->next;
10119 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010120 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010121 if (child != NULL) {
10122 /*
10123 * Attribute uses/declarations.
10124 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010125 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010126 /*
10127 * Attribute wildcard.
10128 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010129 if (IS_SCHEMA(child, "anyAttribute")) {
10130 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010131 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10132 child = child->next;
10133 }
10134 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010135 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010136 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10137 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010138 xmlSchemaPContentErr(ctxt,
10139 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010140 NULL, NULL, node, child, NULL,
10141 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010142 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010143 } else {
10144 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010145 xmlSchemaPContentErr(ctxt,
10146 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010147 NULL, NULL, node, child, NULL,
10148 "(annotation?, ((attribute | attributeGroup)*, "
10149 "anyAttribute?))");
10150 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010151 }
10152 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010153 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010154}
10155
10156/**
10157 * xmlSchemaParseSimpleContent:
10158 * @ctxt: a schema validation context
10159 * @schema: the schema being built
10160 * @node: a subtree containing XML Schema informations
10161 *
10162 * parse a XML schema SimpleContent definition
10163 * *WARNING* this interface is highly subject to change
10164 *
10165 * Returns the type definition or NULL in case of error
10166 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010167static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010168xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10169 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010170{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010171 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010172 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010173 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010174
10175 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010176 return (-1);
10177 /* Not a component, don't create it. */
10178 type = ctxt->ctxtType;
10179 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10180 /*
10181 * Check for illegal attributes.
10182 */
10183 attr = node->properties;
10184 while (attr != NULL) {
10185 if (attr->ns == NULL) {
10186 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010187 xmlSchemaPIllegalAttrErr(ctxt,
10188 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10189 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010190 }
10191 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010192 xmlSchemaPIllegalAttrErr(ctxt,
10193 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10194 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010195 }
10196 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010197 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010198
10199 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010200
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010201 /*
10202 * And now for the children...
10203 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010204 child = node->children;
10205 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010206 /*
10207 * Add the annotation to the complex type ancestor.
10208 */
10209 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10210 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010211 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010212 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010213 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010214 xmlSchemaParseRestriction(ctxt, schema, child,
10215 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010216 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010217 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010218 xmlSchemaParseExtension(ctxt, schema, child,
10219 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010220 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010221 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010222 if (child != NULL) {
10223 xmlSchemaPContentErr(ctxt,
10224 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010225 NULL, NULL, node, child, NULL,
10226 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010227 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010228 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010229}
10230
10231/**
10232 * xmlSchemaParseComplexContent:
10233 * @ctxt: a schema validation context
10234 * @schema: the schema being built
10235 * @node: a subtree containing XML Schema informations
10236 *
10237 * parse a XML schema ComplexContent definition
10238 * *WARNING* this interface is highly subject to change
10239 *
10240 * Returns the type definition or NULL in case of error
10241 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010242static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010243xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10244 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010245{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010246 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010247 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010248 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010249
10250 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010251 return (-1);
10252 /* Not a component, don't create it. */
10253 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010254 /*
10255 * Check for illegal attributes.
10256 */
10257 attr = node->properties;
10258 while (attr != NULL) {
10259 if (attr->ns == NULL) {
10260 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010261 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010262 {
10263 xmlSchemaPIllegalAttrErr(ctxt,
10264 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10265 NULL, NULL, attr);
10266 }
10267 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10268 xmlSchemaPIllegalAttrErr(ctxt,
10269 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10270 NULL, NULL, attr);
10271 }
10272 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010273 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010274
10275 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10276
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010277 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010278 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010279 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010280 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10281 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10282 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010283 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010284 child = node->children;
10285 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010286 /*
10287 * Add the annotation to the complex type ancestor.
10288 */
10289 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10290 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010291 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010292 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010293 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010294 xmlSchemaParseRestriction(ctxt, schema, child,
10295 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010296 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010297 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010298 xmlSchemaParseExtension(ctxt, schema, child,
10299 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010300 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010301 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010302 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010303 xmlSchemaPContentErr(ctxt,
10304 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10305 NULL, NULL, node, child,
10306 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010307 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010308 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010309}
10310
10311/**
10312 * xmlSchemaParseComplexType:
10313 * @ctxt: a schema validation context
10314 * @schema: the schema being built
10315 * @node: a subtree containing XML Schema informations
10316 *
10317 * parse a XML schema Complex Type definition
10318 * *WARNING* this interface is highly subject to change
10319 *
10320 * Returns the type definition or NULL in case of error
10321 */
10322static xmlSchemaTypePtr
10323xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010324 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010325{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010326 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010327 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010328 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010329 xmlAttrPtr attr;
10330 const xmlChar *attrValue;
10331 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010332 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010333 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010334
Daniel Veillard4255d502002-04-16 15:50:10 +000010335
10336 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10337 return (NULL);
10338
Daniel Veillard01fa6152004-06-29 17:04:39 +000010339 ctxtType = ctxt->ctxtType;
10340
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010341 if (topLevel) {
10342 attr = xmlSchemaGetPropNode(node, "name");
10343 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010344 xmlSchemaPMissingAttrErr(ctxt,
10345 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010346 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010347 } else if (xmlSchemaPValAttrNode(ctxt,
10348 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010349 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10350 return (NULL);
10351 }
10352 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010353
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010354 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010355 /*
10356 * Parse as local complex type definition.
10357 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010358 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010359 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10360 if (type == NULL)
10361 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010362 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010363 type->node = node;
10364 type->type = XML_SCHEMA_TYPE_COMPLEX;
10365 /*
10366 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010367 */
10368 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010369 /*
10370 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010371 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010372 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010373 if (type == NULL)
10374 return (NULL);
10375 type->node = node;
10376 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010377 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010378 }
10379 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010380 /*
10381 * Handle attributes.
10382 */
10383 attr = node->properties;
10384 while (attr != NULL) {
10385 if (attr->ns == NULL) {
10386 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10387 /*
10388 * Attribute "id".
10389 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010390 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10391 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010392 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10393 /*
10394 * Attribute "mixed".
10395 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010396 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010397 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010398 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10399 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010400 /*
10401 * Attributes of global complex type definitions.
10402 */
10403 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10404 /* Pass. */
10405 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10406 /*
10407 * Attribute "abstract".
10408 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010409 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10410 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010411 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10412 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10413 /*
10414 * Attribute "final".
10415 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010416 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010417 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010418 if (xmlSchemaPValAttrBlockFinal(attrValue,
10419 &(type->flags),
10420 -1,
10421 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10422 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10423 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010424 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010425 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010426 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010427 type, (xmlNodePtr) attr, NULL,
10428 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010429 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010430 } else
10431 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010432 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10433 /*
10434 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010435 */
10436 attrValue = xmlSchemaGetNodeContent(ctxt,
10437 (xmlNodePtr) attr);
10438 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010439 -1,
10440 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010441 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010442 -1, -1, -1) != 0) {
10443 xmlSchemaPSimpleTypeErr(ctxt,
10444 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010445 type, (xmlNodePtr) attr, NULL,
10446 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010447 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010448 } else
10449 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010450 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010451 xmlSchemaPIllegalAttrErr(ctxt,
10452 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010453 &des, type, attr);
10454 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010455 } else {
10456 xmlSchemaPIllegalAttrErr(ctxt,
10457 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010458 &des, type, attr);
10459 }
10460 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010461 xmlSchemaPIllegalAttrErr(ctxt,
10462 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10463 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010464 }
10465 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010466 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010467 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010468 /*
10469 * Apply default "block" values.
10470 */
10471 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10472 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10473 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10474 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10475 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010476 if (! final) {
10477 /*
10478 * Apply default "block" values.
10479 */
10480 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10481 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10482 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10483 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10484 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010485 /*
10486 * And now for the children...
10487 */
10488 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010489 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010490 child = node->children;
10491 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010492 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10493 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010494 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010495 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010496 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010497 /*
10498 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010499 * Specifying mixed='true' when the <simpleContent>
10500 * alternative is chosen has no effect
10501 */
William M. Bracke7091952004-05-11 15:09:58 +000010502 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10503 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010504 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010505 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010506 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010507 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10508 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010509 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010510 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010511 /*
10512 * SPEC
10513 * "...the third alternative (neither <simpleContent> nor
10514 * <complexContent>) is chosen. This case is understood as shorthand
10515 * for complex content restricting the ·ur-type definition·, and the
10516 * details of the mappings should be modified as necessary.
10517 */
10518 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10519 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010520 /*
10521 * Parse model groups.
10522 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010523 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010524 type->subtypes = (xmlSchemaTypePtr)
10525 xmlSchemaParseModelGroup(ctxt, schema, child,
10526 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010527 child = child->next;
10528 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010529 type->subtypes = (xmlSchemaTypePtr)
10530 xmlSchemaParseModelGroup(ctxt, schema, child,
10531 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010532 child = child->next;
10533 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010534 type->subtypes = (xmlSchemaTypePtr)
10535 xmlSchemaParseModelGroup(ctxt, schema, child,
10536 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010537 child = child->next;
10538 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010539 type->subtypes = (xmlSchemaTypePtr)
10540 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010541 child = child->next;
10542 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010543 /*
10544 * Parse attribute decls/refs.
10545 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010546 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010547 /*
10548 * Parse attribute wildcard.
10549 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010550 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010551 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10552 child = child->next;
10553 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010554 }
10555 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010556 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010557 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010558 &des, type, node, child,
10559 NULL, "(annotation?, (simpleContent | complexContent | "
10560 "((group | all | choice | sequence)?, ((attribute | "
10561 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010562 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010563 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010564 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010565 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010566 return (type);
10567}
10568
Daniel Veillard4255d502002-04-16 15:50:10 +000010569/**
10570 * xmlSchemaParseSchema:
10571 * @ctxt: a schema validation context
10572 * @node: a subtree containing XML Schema informations
10573 *
10574 * parse a XML schema definition from a node set
10575 * *WARNING* this interface is highly subject to change
10576 *
10577 * Returns the internal XML Schema structure built from the resource or
10578 * NULL in case of error
10579 */
10580static xmlSchemaPtr
10581xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10582{
10583 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010584 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010585 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010586 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010587
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010588 /*
10589 * This one is called by xmlSchemaParse only and is used if
10590 * the schema to be parsed was specified via the API; i.e. not
10591 * automatically by the validated instance document.
10592 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010593 if ((ctxt == NULL) || (node == NULL))
10594 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010595 nberrors = ctxt->nberrors;
10596 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010597 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010598 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010599 xmlSchemaImportPtr import;
10600
Daniel Veillard4255d502002-04-16 15:50:10 +000010601 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010602 if (schema == NULL)
10603 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010604 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010605 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010606 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010607 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10608 /*
10609 * TODO: Should we proceed with an invalid target namespace?
10610 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010611 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010612 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10613 /*
10614 * We are parsing the schema for schema!
10615 */
10616 ctxt->isS4S = 1;
10617 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010618 } else {
10619 schema->targetNamespace = NULL;
10620 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010621 /*
10622 * Add the current ns name and location to the import table;
10623 * this is needed to have a consistent mechanism, regardless
10624 * if all schemata are constructed dynamically fired by the
10625 * instance or if the schema to be used was specified via
10626 * the API.
10627 */
10628 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10629 schema->targetNamespace);
10630 if (import == NULL) {
10631 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10632 NULL, NULL, (xmlNodePtr) ctxt->doc,
10633 "Internal error: xmlSchemaParseSchema, "
10634 "failed to add an import entry", NULL);
10635 xmlSchemaFree(schema);
10636 schema = NULL;
10637 return (NULL);
10638 }
10639 import->schemaLocation = ctxt->URL;
10640 /*
10641 * NOTE: We won't set the doc here, otherwise it will be freed
10642 * if the import struct is freed.
10643 * import->doc = ctxt->doc;
10644 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010645 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010646 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10647 } else {
10648 xmlDocPtr doc;
10649
10650 doc = node->doc;
10651
10652 if ((doc != NULL) && (doc->URL != NULL)) {
10653 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10654 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010655 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010656 } else {
10657 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10658 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010659 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010660 }
10661 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010662 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010663 if (ctxt->nberrors != 0) {
10664 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010665 xmlSchemaFree(schema);
10666 schema = NULL;
10667 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010668 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010669 if (schema != NULL)
10670 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010671 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010672#ifdef DEBUG
10673 if (schema == NULL)
10674 xmlGenericError(xmlGenericErrorContext,
10675 "xmlSchemaParse() failed\n");
10676#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010677 return (schema);
10678}
10679
10680/************************************************************************
10681 * *
10682 * Validating using Schemas *
10683 * *
10684 ************************************************************************/
10685
10686/************************************************************************
10687 * *
10688 * Reading/Writing Schemas *
10689 * *
10690 ************************************************************************/
10691
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010692#if 0 /* Will be enabled if it is clear what options are needed. */
10693/**
10694 * xmlSchemaParserCtxtSetOptions:
10695 * @ctxt: a schema parser context
10696 * @options: a combination of xmlSchemaParserOption
10697 *
10698 * Sets the options to be used during the parse.
10699 *
10700 * Returns 0 in case of success, -1 in case of an
10701 * API error.
10702 */
10703static int
10704xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10705 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010706
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010707{
10708 int i;
10709
10710 if (ctxt == NULL)
10711 return (-1);
10712 /*
10713 * WARNING: Change the start value if adding to the
10714 * xmlSchemaParseOption.
10715 */
10716 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10717 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010718 return (-1);
10719 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010720 }
10721 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010722 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010723}
10724
10725/**
10726 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010727 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010728 *
10729 * Returns the option combination of the parser context.
10730 */
10731static int
10732xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010733
10734{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010735 if (ctxt == NULL)
10736 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010737 else
10738 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010739}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010740#endif
10741
Daniel Veillard4255d502002-04-16 15:50:10 +000010742/**
10743 * xmlSchemaNewParserCtxt:
10744 * @URL: the location of the schema
10745 *
10746 * Create an XML Schemas parse context for that file/resource expected
10747 * to contain an XML Schemas file.
10748 *
10749 * Returns the parser context or NULL in case of error
10750 */
10751xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010752xmlSchemaNewParserCtxt(const char *URL)
10753{
Daniel Veillard4255d502002-04-16 15:50:10 +000010754 xmlSchemaParserCtxtPtr ret;
10755
10756 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010757 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010758
10759 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10760 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010761 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010762 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010763 return (NULL);
10764 }
10765 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010766 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010767 ret->dict = xmlDictCreate();
10768 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010769 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010770 return (ret);
10771}
10772
10773/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010774 * xmlSchemaNewMemParserCtxt:
10775 * @buffer: a pointer to a char array containing the schemas
10776 * @size: the size of the array
10777 *
10778 * Create an XML Schemas parse context for that memory buffer expected
10779 * to contain an XML Schemas file.
10780 *
10781 * Returns the parser context or NULL in case of error
10782 */
10783xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010784xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10785{
Daniel Veillard6045c902002-10-09 21:13:59 +000010786 xmlSchemaParserCtxtPtr ret;
10787
10788 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010789 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010790
10791 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10792 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010793 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010794 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010795 return (NULL);
10796 }
10797 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10798 ret->buffer = buffer;
10799 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010800 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010801 return (ret);
10802}
10803
10804/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010805 * xmlSchemaNewDocParserCtxt:
10806 * @doc: a preparsed document tree
10807 *
10808 * Create an XML Schemas parse context for that document.
10809 * NB. The document may be modified during the parsing process.
10810 *
10811 * Returns the parser context or NULL in case of error
10812 */
10813xmlSchemaParserCtxtPtr
10814xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10815{
10816 xmlSchemaParserCtxtPtr ret;
10817
10818 if (doc == NULL)
10819 return (NULL);
10820
10821 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10822 if (ret == NULL) {
10823 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10824 NULL);
10825 return (NULL);
10826 }
10827 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10828 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010829 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010830 /* The application has responsibility for the document */
10831 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010832
10833 return (ret);
10834}
10835
10836/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010837 * xmlSchemaFreeParserCtxt:
10838 * @ctxt: the schema parser context
10839 *
10840 * Free the resources associated to the schema parser context
10841 */
10842void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010843xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10844{
Daniel Veillard4255d502002-04-16 15:50:10 +000010845 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010846 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010847 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010848 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010849 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010850 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010851 xmlFree(ctxt->assemble);
10852 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010853 if (ctxt->vctxt != NULL) {
10854 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10855 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010856 if (ctxt->localImports != NULL)
10857 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010858 if (ctxt->substGroups != NULL)
10859 xmlHashFree(ctxt->substGroups,
10860 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010861 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010862 xmlFree(ctxt);
10863}
10864
10865/************************************************************************
10866 * *
10867 * Building the content models *
10868 * *
10869 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010870
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010871static void
10872xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010873 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010874{
10875 xmlAutomataStatePtr start;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010876 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010877 xmlAutomataStatePtr end;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010878 xmlSchemaSubstGroupPtr substGroup;
10879 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010880
10881 elemDecl = (xmlSchemaElementPtr) particle->children;
10882 /*
10883 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010884 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010885 start = pctxt->state;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010886 end = xmlAutomataNewState(pctxt->am);
10887 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10888 if (substGroup == NULL) {
10889 xmlSchemaPErr(pctxt, GET_NODE(particle),
10890 XML_SCHEMAP_INTERNAL,
10891 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10892 "declaration is marked having a subst. group but none "
10893 "available.\n", elemDecl->name, NULL);
10894 return;
10895 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010896 if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010897 /*
10898 * NOTE that we put the declaration in, even if it's abstract,
10899 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010900 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010901 xmlAutomataNewTransition2(pctxt->am,
10902 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010903 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10904 /*
10905 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010906 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010907 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010908 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10909 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010910 xmlAutomataNewTransition2(pctxt->am,
10911 start, NULL,
10912 member->name, member->targetNamespace, member),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010913 end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010914 }
10915 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010916 int counter;
10917 xmlAutomataStatePtr hop;
10918 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10919 UNBOUNDED : particle->maxOccurs - 1;
10920 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10921
10922 counter =
10923 xmlAutomataNewCounter(pctxt->am, minOccurs,
10924 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010925 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010926
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010927 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010928 xmlAutomataNewTransition2(pctxt->am,
10929 start, NULL,
10930 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010931 hop);
10932 /*
10933 * Add subst. group members.
10934 */
10935 for (i = 0; i < substGroup->members->nbItems; i++) {
10936 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10937 xmlAutomataNewEpsilon(pctxt->am,
10938 xmlAutomataNewTransition2(pctxt->am,
10939 start, NULL,
10940 member->name, member->targetNamespace, member),
10941 hop);
10942 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010943 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10944 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10945 }
10946 if (particle->minOccurs == 0)
10947 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010948 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010949}
10950
10951static void
10952xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10953 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010954{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010955 if (((xmlSchemaElementPtr) particle->children)->flags &
10956 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010957 /*
10958 * Substitution groups.
10959 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010960 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010961 } else {
10962 xmlSchemaElementPtr elemDecl;
10963 xmlAutomataStatePtr start;
10964
10965 elemDecl = (xmlSchemaElementPtr) particle->children;
10966
10967 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010968 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010969 if (particle->maxOccurs == 1) {
10970 start = ctxt->state;
10971 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10972 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10973 } else if ((particle->maxOccurs >= UNBOUNDED) && (particle->minOccurs < 2)) {
10974 /* Special case. */
10975 start = ctxt->state;
10976 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10977 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010978 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010979 } else {
10980 int counter;
10981 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10982 UNBOUNDED : particle->maxOccurs - 1;
10983 int minOccurs = particle->minOccurs < 1 ?
10984 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010985
10986 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010987 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
10988 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10989 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10990 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
10991 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
10992 NULL, counter);
10993 }
10994 if (particle->minOccurs == 0)
10995 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
10996 }
10997}
10998
Daniel Veillard4255d502002-04-16 15:50:10 +000010999/**
11000 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011001 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011002 * @particle: the particle component
11003 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011004 *
11005 * Generate the automata sequence needed for that type
11006 */
11007static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011008xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011009 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011010 const xmlChar * name)
11011{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011012 if (particle == NULL) {
11013 xmlSchemaPErr(ctxt, NULL,
11014 XML_SCHEMAP_INTERNAL,
11015 "Internal error: xmlSchemaBuildAContentModel, "
11016 "particle is NULL.\n", NULL, NULL);
11017 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011018 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011019 if (particle->children == NULL) {
11020 xmlSchemaPErr(ctxt, GET_NODE(particle),
11021 XML_SCHEMAP_INTERNAL,
11022 "Internal error: xmlSchemaBuildAContentModel, "
11023 "no term on particle.\n", NULL, NULL);
11024 return;
11025 }
11026
11027 switch (particle->children->type) {
11028 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011029 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011030 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011031 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011032
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011033 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011034
Daniel Veillardc0826a72004-08-10 14:17:33 +000011035 start = ctxt->state;
11036 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011037
11038 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011039 if (wild->any == 1) {
11040 /*
11041 * We need to add both transitions:
11042 *
11043 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011044 */
11045 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011046 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011047 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011048 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11049 /*
11050 * 2. the {"*"} for elements in no namespace.
11051 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011052 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011053 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011054 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011055 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11056
11057 } else if (wild->nsSet != NULL) {
11058 ns = wild->nsSet;
11059 do {
11060 ctxt->state = start;
11061 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011062 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011063 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11064 ns = ns->next;
11065 } while (ns != NULL);
11066
11067 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011068
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011069 /*
11070 * Lead nodes with the negated namespace to the sink-state
11071 * {"*", "##other"}.
11072 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011073 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011074 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011075 /*
11076 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011077 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011078 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011079 ctxt->state = 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);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011082 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011083 } else {
11084 int counter;
11085 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011086 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011087 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011088 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011089 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011090
Daniel Veillardc0826a72004-08-10 14:17:33 +000011091 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011092 hop = xmlAutomataNewState(ctxt->am);
11093 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011094 ctxt->state =
11095 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011096 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011097 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011098 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011099 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011100 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011101 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011102 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011103 ns = wild->nsSet;
11104 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011105 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011106 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011107 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011108 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11109 ns = ns->next;
11110 } while (ns != NULL);
11111
11112 } else if (wild->negNsSet != NULL) {
11113 xmlAutomataStatePtr deadEnd;
11114
11115 deadEnd = xmlAutomataNewState(ctxt->am);
11116 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011117 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011118 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011119 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011120 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011121 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011122 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11123 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11124 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011125 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011126 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011127 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011128 ctxt->state = end;
11129 break;
11130 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011131 case XML_SCHEMA_TYPE_ELEMENT:
11132 xmlSchemaBuildContentModelForElement(ctxt, particle);
11133 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011134 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011135 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011136
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011137 /*
11138 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011139 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011140 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011141 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11142 sub = particle->children->children;
11143 while (sub != NULL) {
11144 xmlSchemaBuildAContentModel(ctxt,
11145 (xmlSchemaParticlePtr) sub, name);
11146 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011147 }
11148 } else {
11149 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011150
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011151 if (particle->maxOccurs >= UNBOUNDED) {
11152 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011153 xmlAutomataStatePtr tmp;
11154 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011155
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011156 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011157 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011158 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011159
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011160 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011161 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011162
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011163 sub = particle->children->children;
11164 while (sub != NULL) {
11165 xmlSchemaBuildAContentModel(ctxt,
11166 (xmlSchemaParticlePtr) sub, name);
11167 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011168 }
11169 tmp = ctxt->state;
11170 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11171 oldstate, counter);
11172 ctxt->state =
11173 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11174 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011175
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011176 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011177 sub = particle->children->children;
11178 while (sub != NULL) {
11179 xmlSchemaBuildAContentModel(ctxt,
11180 (xmlSchemaParticlePtr) sub, name);
11181 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011182 }
11183 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11184 oldstate);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011185 if (particle->minOccurs == 0) {
11186 xmlAutomataNewEpsilon(ctxt->am,
11187 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011188 }
11189 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011190 } else if ((particle->maxOccurs > 1)
11191 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011192 xmlAutomataStatePtr tmp;
11193 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011194
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011195 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011196 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011197 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011198
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011199 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011200 particle->minOccurs - 1,
11201 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011202
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011203 sub = particle->children->children;
11204 while (sub != NULL) {
11205 xmlSchemaBuildAContentModel(ctxt,
11206 (xmlSchemaParticlePtr) sub, name);
11207 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011208 }
11209 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011210 xmlAutomataNewCountedTrans(ctxt->am,
11211 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011212 ctxt->state =
11213 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11214 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011215 if (particle->minOccurs == 0) {
11216 xmlAutomataNewEpsilon(ctxt->am,
11217 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011218 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011219 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011220 sub = particle->children->children;
11221 while (sub != NULL) {
11222 xmlSchemaBuildAContentModel(ctxt,
11223 (xmlSchemaParticlePtr) sub, name);
11224 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011225 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011226 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011227 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11228 ctxt->state);
11229 }
11230 }
11231 }
11232 break;
11233 }
11234 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011235 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011236 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011237
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011238 start = ctxt->state;
11239 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011240
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011241 /*
11242 * iterate over the subtypes and remerge the end with an
11243 * epsilon transition
11244 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011245 if (particle->maxOccurs == 1) {
11246 sub = particle->children->children;
11247 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011248 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011249 xmlSchemaBuildAContentModel(ctxt,
11250 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011251 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011252 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011253 }
11254 } else {
11255 int counter;
11256 xmlAutomataStatePtr hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011257 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11258 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011259 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011260 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011261
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011262 /*
11263 * use a counter to keep track of the number of transtions
11264 * which went through the choice.
11265 */
11266 counter =
11267 xmlAutomataNewCounter(ctxt->am, minOccurs,
11268 maxOccurs);
11269 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011270
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011271 sub = particle->children->children;
11272 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011273 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011274 xmlSchemaBuildAContentModel(ctxt,
11275 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011276 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011277 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011278 }
11279 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
11280 counter);
11281 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
11282 counter);
11283 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011284 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011285 xmlAutomataNewEpsilon(ctxt->am, start, end);
11286 }
11287 ctxt->state = end;
11288 break;
11289 }
11290 case XML_SCHEMA_TYPE_ALL:{
11291 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011292 xmlSchemaParticlePtr sub;
11293 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011294 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011295
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011296 sub = (xmlSchemaParticlePtr) particle->children->children;
11297 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011298 break;
11299 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011300 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011301 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011302
11303 elemDecl = (xmlSchemaElementPtr) sub->children;
11304 if (elemDecl == NULL) {
11305 xmlSchemaPErr(ctxt, NULL,
11306 XML_SCHEMAP_INTERNAL,
11307 "Internal error: xmlSchemaBuildAContentModel, "
11308 "<element> particle a NULL term.\n", NULL, NULL);
11309 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011310 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011311 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011312 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011313 * {particles} of the group must be 0 or 1; this is
11314 * already ensured during the parse of the content of
11315 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011316 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011317 if ((sub->minOccurs == 1) &&
11318 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011319 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011320 ctxt->state,
11321 elemDecl->name,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011322 elemDecl->targetNamespace,
11323 1, 1, elemDecl);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011324 } else if ((sub->minOccurs == 0) &&
11325 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011326
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011327 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011328 ctxt->state,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011329 elemDecl->name,
11330 elemDecl->targetNamespace,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011331 0,
11332 1,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011333 elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011334 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011335 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011336 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011337 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011338 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011339 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011340 break;
11341 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011342 default:
11343 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011344 "Internal error: xmlSchemaBuildAContentModel, found "
11345 "unexpected term of type %d in content model of complex "
11346 "type '%s'.\n",
11347 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011348 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011349 }
11350}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011351
Daniel Veillard4255d502002-04-16 15:50:10 +000011352/**
11353 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011354 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011355 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011356 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011357 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011358 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011359 */
11360static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011361xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011362 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011363 const xmlChar * name)
11364{
Daniel Veillard4255d502002-04-16 15:50:10 +000011365 xmlAutomataStatePtr start;
11366
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011367 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11368 (type->contModel != NULL) ||
11369 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11370 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011371 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011372
11373#ifdef DEBUG_CONTENT
11374 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011375 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011376#endif
11377
Daniel Veillard4255d502002-04-16 15:50:10 +000011378 ctxt->am = xmlNewAutomata();
11379 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011380 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011381 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011382 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011383 }
11384 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011385 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011386 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011387 type->contModel = xmlAutomataCompile(ctxt->am);
11388 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011389 xmlSchemaPCustomErr(ctxt,
11390 XML_SCHEMAP_INTERNAL,
11391 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011392 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011393 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011394 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011395 XML_SCHEMAP_NOT_DETERMINISTIC,
11396 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011397 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011398 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011399 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011400#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011401 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011402 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011403 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011404#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011405 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011406 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011407 xmlFreeAutomata(ctxt->am);
11408 ctxt->am = NULL;
11409}
11410
11411/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011412 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011413 * @elem: the schema element context
11414 * @ctxt: the schema parser context
11415 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011416 * Resolves the references of an element declaration
11417 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011418 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011419 */
11420static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011421xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011422 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011423 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011424 const xmlChar * context ATTRIBUTE_UNUSED,
11425 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011426{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011427 if ((ctxt == NULL) || (elemDecl == NULL) ||
11428 ((elemDecl != NULL) &&
11429 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011430 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011431 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011432
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011433 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011434 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011435
11436 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011437 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011438 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011439 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011440 elemDecl->namedTypeNs);
11441 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011442 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011443 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011444 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011445 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011446 XML_SCHEMA_TYPE_BASIC, "type definition");
11447 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011448 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011449 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011450 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011451 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011452
Daniel Veillardc0826a72004-08-10 14:17:33 +000011453 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011454 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011455 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011456 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011457 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11458 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011459 if (substHead == NULL) {
11460 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011461 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011462 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011463 "substitutionGroup", elemDecl->substGroup,
11464 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011465 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011466 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011467 /*
11468 * Set the "substitution group affiliation".
11469 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011470 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011471 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011472 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011473 * (type definition)...otherwise the {type definition} of the
11474 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011475 * the substitutionGroup [attribute], if present
11476 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011477 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011478 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011479 }
11480 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011481 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11482 (elemDecl->substGroup == NULL))
11483 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011484}
11485
11486/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011487 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011488 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011489 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011490 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011491 * Checks and builds the "member type definitions" property of the union
11492 * simple type. This handles part (1), part (2) is done in
11493 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11494 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011495 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011496 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011497static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011498xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11499 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011500{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011501
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011502 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011503 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011504
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011505 /*
11506 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11507 * define the explicit members as the type definitions ·resolved·
11508 * to by the items in the ·actual value· of the memberTypes [attribute],
11509 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011510 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011511 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011512 /*
11513 * Resolve references.
11514 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011515 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011516 lastLink = NULL;
11517 while (link != NULL) {
11518 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011519
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011520 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11521 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11522
11523 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11524 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11525 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011526 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011527 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11528 /*
11529 * Remove the member type link.
11530 */
11531 if (lastLink == NULL)
11532 type->memberTypes = link->next;
11533 else
11534 lastLink->next = link->next;
11535 newLink = link;
11536 link = link->next;
11537 xmlFree(newLink);
11538 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011539 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011540 lastLink = link;
11541 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011542 }
11543 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011544 /*
11545 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011546 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011547 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011548 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011549 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11550 if (link == NULL) {
11551 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11552 return (-1);
11553 }
11554 link->type = memberType;
11555 link->next = NULL;
11556 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011557 type->memberTypes = link;
11558 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011559 lastLink->next = link;
11560 lastLink = link;
11561 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011562 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011563 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011564}
11565
Daniel Veillard4255d502002-04-16 15:50:10 +000011566/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011567 * xmlSchemaIsDerivedFromBuiltInType:
11568 * @ctxt: the schema parser context
11569 * @type: the type definition
11570 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011571 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011572 *
11573 * Returns 1 if the type has the given value type, or
11574 * is derived from such a type.
11575 */
William M. Brack803812b2004-06-03 02:11:24 +000011576static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011577xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011578{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011579 if (type == NULL)
11580 return (0);
11581 if (IS_COMPLEX_TYPE(type))
11582 return (0);
11583 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11584 if (type->builtInType == valType)
11585 return(1);
11586 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11587 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11588 return (0);
11589 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11590 } else
11591 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011592
11593 return (0);
11594}
11595
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011596#if 0
11597/**
11598 * xmlSchemaIsDerivedFromBuiltInType:
11599 * @ctxt: the schema parser context
11600 * @type: the type definition
11601 * @valType: the value type
11602 *
11603 *
11604 * Returns 1 if the type has the given value type, or
11605 * is derived from such a type.
11606 */
11607static int
11608xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11609{
11610 if (type == NULL)
11611 return (0);
11612 if (IS_COMPLEX_TYPE(type))
11613 return (0);
11614 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11615 if (type->builtInType == valType)
11616 return(1);
11617 return (0);
11618 } else
11619 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11620
11621 return (0);
11622}
11623#endif
11624
11625static xmlSchemaTypePtr
11626xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11627{
11628 if (type == NULL)
11629 return (NULL);
11630 if (IS_COMPLEX_TYPE(type))
11631 return (NULL);
11632 if (type->type == XML_SCHEMA_TYPE_BASIC)
11633 return(type);
11634 else
11635 return(xmlSchemaQueryBuiltInType(type->subtypes));
11636
11637 return (NULL);
11638}
11639
Daniel Veillard3646d642004-06-02 19:19:14 +000011640/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011641 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011642 * @type: the simpleType definition
11643 *
11644 * Returns the primitive type of the given type or
11645 * NULL in case of error.
11646 */
11647static xmlSchemaTypePtr
11648xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11649{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011650
Daniel Veillard01fa6152004-06-29 17:04:39 +000011651 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011652 /*
11653 * Note that anySimpleType is actually not a primitive type
11654 * but we need that here.
11655 */
11656 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11657 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011658 return (type);
11659 type = type->baseType;
11660 }
11661
11662 return (NULL);
11663}
11664
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011665#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011666/**
11667 * xmlSchemaGetBuiltInTypeAncestor:
11668 * @type: the simpleType definition
11669 *
11670 * Returns the primitive type of the given type or
11671 * NULL in case of error.
11672 */
11673static xmlSchemaTypePtr
11674xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11675{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011676 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011677 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011678 while (type != NULL) {
11679 if (type->type == XML_SCHEMA_TYPE_BASIC)
11680 return (type);
11681 type = type->baseType;
11682 }
11683
11684 return (NULL);
11685}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011686#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011687
Daniel Veillard01fa6152004-06-29 17:04:39 +000011688/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011689 * xmlSchemaBuildAttributeUsesOwned:
11690 * @ctxt: the schema parser context
11691 * @type: the complex type definition
11692 * @cur: the attribute declaration list
11693 * @lastUse: the top of the attribute use list
11694 *
11695 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011696 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011697 * xmlSchemaBuildAttributeValidation only.
11698 */
11699static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011700xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011701 xmlSchemaAttributePtr cur,
11702 xmlSchemaAttributeLinkPtr *uses,
11703 xmlSchemaAttributeLinkPtr *lastUse)
11704{
11705 xmlSchemaAttributeLinkPtr tmp;
11706 while (cur != NULL) {
11707 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011708 /*
11709 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11710 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011711 * <attributeGroup> [children], if any."
11712 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011713 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11714 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011715 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011716 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011717 }
11718 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011719 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011720 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011721 */
11722 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011723 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11724 if (tmp == NULL) {
11725 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11726 return (-1);
11727 }
11728 tmp->attr = cur;
11729 tmp->next = NULL;
11730 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011731 *uses = tmp;
11732 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011733 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011734 *lastUse = tmp;
11735 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011736 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011737 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011738 return (0);
11739}
11740
Daniel Veillard50355f02004-06-08 17:52:16 +000011741/**
11742 * xmlSchemaCloneWildcardNsConstraints:
11743 * @ctxt: the schema parser context
11744 * @dest: the destination wildcard
11745 * @source: the source wildcard
11746 *
11747 * Clones the namespace constraints of source
11748 * and assignes them to dest.
11749 * Returns -1 on internal error, 0 otherwise.
11750 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011751static int
11752xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11753 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011754 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011755{
11756 xmlSchemaWildcardNsPtr cur, tmp, last;
11757
11758 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011759 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011760 (*dest)->any = source->any;
11761 cur = source->nsSet;
11762 last = NULL;
11763 while (cur != NULL) {
11764 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11765 if (tmp == NULL)
11766 return(-1);
11767 tmp->value = cur->value;
11768 if (last == NULL)
11769 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011770 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011771 last->next = tmp;
11772 last = tmp;
11773 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011774 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011775 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011776 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011777 if (source->negNsSet != NULL) {
11778 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11779 if ((*dest)->negNsSet == NULL)
11780 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011781 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011782 } else
11783 (*dest)->negNsSet = NULL;
11784 return(0);
11785}
11786
Daniel Veillard50355f02004-06-08 17:52:16 +000011787/**
11788 * xmlSchemaUnionWildcards:
11789 * @ctxt: the schema parser context
11790 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011791 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011792 *
11793 * Unions the namespace constraints of the given wildcards.
11794 * @completeWild will hold the resulting union.
11795 * Returns a positive error code on failure, -1 in case of an
11796 * internal error, 0 otherwise.
11797 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011798static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011799xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011800 xmlSchemaWildcardPtr completeWild,
11801 xmlSchemaWildcardPtr curWild)
11802{
11803 xmlSchemaWildcardNsPtr cur, curB, tmp;
11804
11805 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011806 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011807 * value.
11808 */
11809 if ((completeWild->any == curWild->any) &&
11810 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11811 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011812
Daniel Veillard3646d642004-06-02 19:19:14 +000011813 if ((completeWild->negNsSet == NULL) ||
11814 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011815
Daniel Veillard3646d642004-06-02 19:19:14 +000011816 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011817 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011818
11819 /*
11820 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011821 */
11822 cur = completeWild->nsSet;
11823 while (cur != NULL) {
11824 found = 0;
11825 curB = curWild->nsSet;
11826 while (curB != NULL) {
11827 if (cur->value == curB->value) {
11828 found = 1;
11829 break;
11830 }
11831 curB = curB->next;
11832 }
11833 if (!found)
11834 break;
11835 cur = cur->next;
11836 }
11837 if (found)
11838 return(0);
11839 } else
11840 return(0);
11841 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011842 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011843 /*
11844 * 2 If either O1 or O2 is any, then any must be the value
11845 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011846 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011847 if (completeWild->any == 0) {
11848 completeWild->any = 1;
11849 if (completeWild->nsSet != NULL) {
11850 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11851 completeWild->nsSet = NULL;
11852 }
11853 if (completeWild->negNsSet != NULL) {
11854 xmlFree(completeWild->negNsSet);
11855 completeWild->negNsSet = NULL;
11856 }
11857 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011858 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011859 }
11860 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011861 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011862 * then the union of those sets must be the value.
11863 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011864 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011865 int found;
11866 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011867
Daniel Veillard3646d642004-06-02 19:19:14 +000011868 cur = curWild->nsSet;
11869 start = completeWild->nsSet;
11870 while (cur != NULL) {
11871 found = 0;
11872 curB = start;
11873 while (curB != NULL) {
11874 if (cur->value == curB->value) {
11875 found = 1;
11876 break;
11877 }
11878 curB = curB->next;
11879 }
11880 if (!found) {
11881 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011882 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011883 return (-1);
11884 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011885 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011886 completeWild->nsSet = tmp;
11887 }
11888 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011889 }
11890
Daniel Veillard3646d642004-06-02 19:19:14 +000011891 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011892 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011893 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011894 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011895 * or ·absent·), then a pair of not and ·absent· must be the value.
11896 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011897 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011898 (curWild->negNsSet != NULL) &&
11899 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11900 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011901
11902 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011903 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011904 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011905 * 5.
11906 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011907 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011908 (completeWild->negNsSet->value != NULL) &&
11909 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011910 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011911 (curWild->negNsSet->value != NULL) &&
11912 (completeWild->nsSet != NULL))) {
11913
11914 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011915
Daniel Veillard3646d642004-06-02 19:19:14 +000011916 if (completeWild->nsSet != NULL) {
11917 cur = completeWild->nsSet;
11918 curB = curWild->negNsSet;
11919 } else {
11920 cur = curWild->nsSet;
11921 curB = completeWild->negNsSet;
11922 }
11923 nsFound = 0;
11924 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011925 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011926 absentFound = 1;
11927 else if (cur->value == curB->value)
11928 nsFound = 1;
11929 if (nsFound && absentFound)
11930 break;
11931 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011932 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011933
11934 if (nsFound && absentFound) {
11935 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011936 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011937 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011938 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011939 completeWild->any = 1;
11940 if (completeWild->nsSet != NULL) {
11941 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11942 completeWild->nsSet = NULL;
11943 }
11944 if (completeWild->negNsSet != NULL) {
11945 xmlFree(completeWild->negNsSet);
11946 completeWild->negNsSet = NULL;
11947 }
11948 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011949 /*
11950 * 5.2 If the set S includes the negated namespace name
11951 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000011952 * be the value.
11953 */
11954 if (completeWild->nsSet != NULL) {
11955 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11956 completeWild->nsSet = NULL;
11957 }
11958 if (completeWild->negNsSet == NULL) {
11959 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11960 if (completeWild->negNsSet == NULL)
11961 return (-1);
11962 }
11963 completeWild->negNsSet->value = NULL;
11964 } else if ((!nsFound) && absentFound) {
11965 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011966 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000011967 * namespace name, then the union is not expressible.
11968 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011969 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000011970 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011971 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011972 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011973 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011974 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011975 /*
11976 * 5.4 If the set S does not include either the negated namespace
11977 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000011978 * and a namespace name must be the value.
11979 */
11980 if (completeWild->negNsSet == NULL) {
11981 if (completeWild->nsSet != NULL) {
11982 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11983 completeWild->nsSet = NULL;
11984 }
11985 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11986 if (completeWild->negNsSet == NULL)
11987 return (-1);
11988 completeWild->negNsSet->value = curWild->negNsSet->value;
11989 }
11990 }
11991 return (0);
11992 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011993 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011994 * 6.
11995 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011996 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011997 (completeWild->negNsSet->value == NULL) &&
11998 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011999 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012000 (curWild->negNsSet->value == NULL) &&
12001 (completeWild->nsSet != NULL))) {
12002
12003 if (completeWild->nsSet != NULL) {
12004 cur = completeWild->nsSet;
12005 } else {
12006 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012007 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012008 while (cur != NULL) {
12009 if (cur->value == NULL) {
12010 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012011 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012012 * value.
12013 */
12014 completeWild->any = 1;
12015 if (completeWild->nsSet != NULL) {
12016 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12017 completeWild->nsSet = NULL;
12018 }
12019 if (completeWild->negNsSet != NULL) {
12020 xmlFree(completeWild->negNsSet);
12021 completeWild->negNsSet = NULL;
12022 }
12023 return (0);
12024 }
12025 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012026 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012027 if (completeWild->negNsSet == NULL) {
12028 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012029 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012030 * and ·absent· must be the value.
12031 */
12032 if (completeWild->nsSet != NULL) {
12033 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12034 completeWild->nsSet = NULL;
12035 }
12036 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12037 if (completeWild->negNsSet == NULL)
12038 return (-1);
12039 completeWild->negNsSet->value = NULL;
12040 }
12041 return (0);
12042 }
12043 return (0);
12044
12045}
12046
Daniel Veillard50355f02004-06-08 17:52:16 +000012047/**
12048 * xmlSchemaIntersectWildcards:
12049 * @ctxt: the schema parser context
12050 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012051 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012052 *
12053 * Intersects the namespace constraints of the given wildcards.
12054 * @completeWild will hold the resulting intersection.
12055 * Returns a positive error code on failure, -1 in case of an
12056 * internal error, 0 otherwise.
12057 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012058static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012059xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012060 xmlSchemaWildcardPtr completeWild,
12061 xmlSchemaWildcardPtr curWild)
12062{
William M. Brack803812b2004-06-03 02:11:24 +000012063 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012064
12065 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012066 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012067 * value.
12068 */
12069 if ((completeWild->any == curWild->any) &&
12070 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12071 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012072
Daniel Veillard3646d642004-06-02 19:19:14 +000012073 if ((completeWild->negNsSet == NULL) ||
12074 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012075
Daniel Veillard3646d642004-06-02 19:19:14 +000012076 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012077 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012078
12079 /*
12080 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012081 */
12082 cur = completeWild->nsSet;
12083 while (cur != NULL) {
12084 found = 0;
12085 curB = curWild->nsSet;
12086 while (curB != NULL) {
12087 if (cur->value == curB->value) {
12088 found = 1;
12089 break;
12090 }
12091 curB = curB->next;
12092 }
12093 if (!found)
12094 break;
12095 cur = cur->next;
12096 }
12097 if (found)
12098 return(0);
12099 } else
12100 return(0);
12101 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012102 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012103 /*
12104 * 2 If either O1 or O2 is any, then the other must be the value.
12105 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012106 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012107 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012108 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012109 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012110 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012111 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012112 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12113 * name or ·absent·) and the other is a set of (namespace names or
12114 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012115 * the set, minus ·absent· if it was in the set, must be the value.
12116 */
12117 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12118 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12119 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012120
Daniel Veillard3646d642004-06-02 19:19:14 +000012121 if (completeWild->nsSet == NULL) {
12122 neg = completeWild->negNsSet->value;
12123 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12124 return(-1);
12125 } else
12126 neg = curWild->negNsSet->value;
12127 /*
12128 * Remove absent and negated.
12129 */
12130 prev = NULL;
12131 cur = completeWild->nsSet;
12132 while (cur != NULL) {
12133 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012134 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012135 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012136 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012137 prev->next = cur->next;
12138 xmlFree(cur);
12139 break;
12140 }
12141 prev = cur;
12142 cur = cur->next;
12143 }
12144 if (neg != NULL) {
12145 prev = NULL;
12146 cur = completeWild->nsSet;
12147 while (cur != NULL) {
12148 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012149 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012150 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012151 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012152 prev->next = cur->next;
12153 xmlFree(cur);
12154 break;
12155 }
12156 prev = cur;
12157 cur = cur->next;
12158 }
12159 }
12160
12161 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 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012165 * then the intersection of those sets must be the value.
12166 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012167 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012168 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012169
Daniel Veillard3646d642004-06-02 19:19:14 +000012170 cur = completeWild->nsSet;
12171 prev = NULL;
12172 while (cur != NULL) {
12173 found = 0;
12174 curB = curWild->nsSet;
12175 while (curB != NULL) {
12176 if (cur->value == curB->value) {
12177 found = 1;
12178 break;
12179 }
12180 curB = curB->next;
12181 }
12182 if (!found) {
12183 if (prev == NULL)
12184 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012185 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012186 prev->next = cur->next;
12187 tmp = cur->next;
12188 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012189 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012190 continue;
12191 }
12192 prev = cur;
12193 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012194 }
12195
Daniel Veillard3646d642004-06-02 19:19:14 +000012196 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012197 }
12198 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012199 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012200 */
12201 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012202 (curWild->negNsSet != NULL) &&
12203 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012204 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012205 (curWild->negNsSet->value != NULL)) {
12206
12207 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012208 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012209 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012210 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012211 }
12212 /*
12213 * 6 If the one is a negation of a namespace name and the other
12214 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012215 * of a namespace name must be the value.
12216 */
12217 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12218 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012219 (completeWild->negNsSet->value == NULL)) {
12220 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012221 }
12222 return(0);
12223}
12224
Daniel Veillard50355f02004-06-08 17:52:16 +000012225/**
12226 * xmlSchemaIsWildcardNsConstraintSubset:
12227 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012228 * @sub: the first wildcard
12229 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012230 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012231 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12232 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012233 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012234 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012235 */
12236static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012237xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12238 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012239{
Daniel Veillard50355f02004-06-08 17:52:16 +000012240 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012241 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012242 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012243 if (super->any)
12244 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012245 /*
12246 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12247 * 2.2 super must be a pair of not and the same value.
12248 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012249 if ((sub->negNsSet != NULL) &&
12250 (super->negNsSet != NULL) &&
12251 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012252 return (0);
12253 /*
12254 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012255 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012256 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012257 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012258 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012259 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012260 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012261 xmlSchemaWildcardNsPtr cur, curB;
12262 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012263
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012264 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012265 while (cur != NULL) {
12266 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012267 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012268 while (curB != NULL) {
12269 if (cur->value == curB->value) {
12270 found = 1;
12271 break;
12272 }
12273 curB = curB->next;
12274 }
12275 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012276 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012277 cur = cur->next;
12278 }
12279 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012280 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012281 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012282 xmlSchemaWildcardNsPtr cur;
12283 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012284 * 3.2.2 super must be a pair of not and a namespace name or
12285 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012286 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012287 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012288 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012289 if (cur->value == super->negNsSet->value)
12290 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012291 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012292 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012293 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012294 }
12295 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012296 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012297}
12298
12299/**
12300 * xmlSchemaBuildCompleteAttributeWildcard:
12301 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012302 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012303 * @completeWild: the resulting complete wildcard
12304 *
12305 * Returns -1 in case of an internal error, 0 otherwise.
12306 */
12307static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012308xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012309 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012310 xmlSchemaWildcardPtr *completeWild)
12311{
Daniel Veillard3646d642004-06-02 19:19:14 +000012312 while (attrs != NULL) {
12313 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12314 xmlSchemaAttributeGroupPtr group;
12315
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012316 group = (xmlSchemaAttributeGroupPtr) attrs;
12317 /*
12318 * Handle attribute group references.
12319 */
12320 if (group->ref != NULL) {
12321 if (group->refItem == NULL) {
12322 /*
12323 * TODO: Should we raise a warning here?
12324 */
12325 /*
12326 * The referenced attribute group definition could not
12327 * be resolved beforehand, so skip.
12328 */
12329 attrs = attrs->next;
12330 continue;
12331 } else
12332 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012333 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012334 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012335 * For every attribute group definition, an intersected wildcard
12336 * will be created (assumed that a wildcard exists on the
12337 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012338 * at all).
12339 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12340 * that the intersection will be performed only once.
12341 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012342 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12343 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012344 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012345 group->attributes, &group->attributeWildcard) == -1)
12346 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012347 }
12348 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012349 }
12350 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012351 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012352 /*
12353 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012354 *
12355 * Although the complete wildcard might not correspond to any
12356 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012357 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012358 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12359 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12360 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012361 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012362 completeWild, group->attributeWildcard) == -1)
12363 return (-1);
12364 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012365 (*completeWild)->node = group->attributeWildcard->node;
12366 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012367 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012368 }
12369 }
12370 attrs = attrs->next;
12371 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012372
12373 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012374}
12375
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012376static int
12377xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12378 int *fixed,
12379 const xmlChar **value,
12380 xmlSchemaValPtr *val)
12381{
12382 *fixed = 0;
12383 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012384 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012385 *val = NULL;
12386
12387 if (item->defValue == NULL)
12388 item = item->refDecl;
12389
12390 if (item == NULL)
12391 return (0);
12392
12393 if (item->defValue != NULL) {
12394 *value = item->defValue;
12395 if (val != 0)
12396 *val = item->defVal;
12397 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12398 *fixed = 1;
12399 return (1);
12400 }
12401 return (0);
12402}
Daniel Veillard3646d642004-06-02 19:19:14 +000012403/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012404 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012405 * @wild: the wildcard
12406 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012407 *
12408 * Validation Rule: Wildcard allows Namespace Name
12409 * (cvc-wildcard-namespace)
12410 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012411 *
12412 * Returns 1 if the given namespace matches the wildcard,
12413 * 0 otherwise.
12414 */
12415static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012416xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12417 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012418{
12419 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012420 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012421
12422 if (wild->any)
12423 return(1);
12424 else if (wild->nsSet != NULL) {
12425 xmlSchemaWildcardNsPtr cur;
12426
12427 cur = wild->nsSet;
12428 while (cur != NULL) {
12429 if (xmlStrEqual(cur->value, ns))
12430 return(1);
12431 cur = cur->next;
12432 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012433 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012434 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012435 return(1);
12436
Daniel Veillard3646d642004-06-02 19:19:14 +000012437 return(0);
12438}
12439
12440/**
12441 * xmlSchemaBuildAttributeValidation:
12442 * @ctxt: the schema parser context
12443 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012444 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012445 *
12446 * Builds the wildcard and the attribute uses on the given complex type.
12447 * Returns -1 if an internal error occurs, 0 otherwise.
12448 */
12449static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012450xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12451 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012452{
12453 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012454 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12455 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012456 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012457 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012458 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012459 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012460
Daniel Veillard01fa6152004-06-29 17:04:39 +000012461 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012462 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012463 * Complex Type Definition with complex content Schema Component.
12464 *
12465 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012466 * TODO: Add checks for absent referenced attribute declarations and
12467 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012468 */
12469 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012470 PERROR_INT("xmlSchemaBuildAttributeValidation",
12471 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012472 return (-1);
12473 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012474 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012475 PERROR_INT("xmlSchemaBuildAttributeValidation",
12476 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012477 return (-1);
12478 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012479 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012480 /*
12481 * Inherit the attribute uses of the base type.
12482 */
12483 /*
12484 * NOTE: It is allowed to "extend" the anyType complex type.
12485 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012486 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012487 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012488 for (cur = baseType->attributeUses; cur != NULL;
12489 cur = cur->next) {
12490 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012491 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12492 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012493 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012494 "building attribute uses of complexType", NULL);
12495 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012496 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012497 tmp->attr = cur->attr;
12498 tmp->next = NULL;
12499 if (type->attributeUses == NULL) {
12500 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012501 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012502 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012503 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012504 }
12505 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012506 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012507 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012508 /*
12509 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012510 */
12511 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12512 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012513 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012514 * NOTE: During the parse time, the wildcard is created on the complexType
12515 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012516 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012517 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012518 PERROR_INT("xmlSchemaBuildAttributeValidation",
12519 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012520 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012521 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012522
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012523 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12524 ((IS_ANYTYPE(baseType)) ||
12525 ((baseType != NULL) &&
12526 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12527 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012528 if (type->attributeWildcard != NULL) {
12529 /*
12530 * Union the complete wildcard with the base wildcard.
12531 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012532 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012533 baseType->attributeWildcard) == -1)
12534 return (-1);
12535 } else {
12536 /*
12537 * Just inherit the wildcard.
12538 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012539 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012540 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012541 * wildcard is shared.
12542 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012543 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012544 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012545 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012546
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012547 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12548 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012549 /*
12550 * Derivation Valid (Restriction, Complex)
12551 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012552 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012553 if (baseType->attributeWildcard == NULL) {
12554 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012555 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012556 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012557 "The type has an attribute wildcard, "
12558 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012559 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012560 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012561 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012562 } else if (xmlSchemaCheckCOSNSSubset(
12563 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012564 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012565 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012566 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012567 NULL, type, NULL,
12568 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012569 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012570 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12571 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012572 return (1);
12573 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012574 /* 4.3 Unless the {base type definition} is the ·ur-type
12575 * definition·, the complex type definition's {attribute
12576 * wildcard}'s {process contents} must be identical to or
12577 * stronger than the {base type definition}'s {attribute
12578 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012579 * than lax is stronger than skip.
12580 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012581 if ((! IS_ANYTYPE(baseType)) &&
12582 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012583 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012584 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012585 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012586 NULL, type, NULL,
12587 "The 'process contents' of the attribute wildcard is "
12588 "weaker than the one in the base type %s",
12589 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012590 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012591 return (1);
12592 }
12593 }
12594 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12595 /*
12596 * Derivation Valid (Extension)
12597 * At this point the type and the base have both, either
12598 * no wildcard or a wildcard.
12599 */
12600 if ((baseType->attributeWildcard != NULL) &&
12601 (baseType->attributeWildcard != type->attributeWildcard)) {
12602 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012603 if (xmlSchemaCheckCOSNSSubset(
12604 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012605 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012606 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012607 NULL, type, NULL,
12608 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012609 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012610 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12611 FREE_AND_NULL(str)
12612 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012613 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012614 }
12615 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012616
Daniel Veillard3646d642004-06-02 19:19:14 +000012617 /*
12618 * Gather attribute uses defined by this type.
12619 */
12620 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012621 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012622 &uses, &lastUse) == -1) {
12623 return (-1);
12624 }
12625 }
12626 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012627 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012628 * not have identical {name}s and {target namespace}s."
12629 *
12630 * For "extension" this is done further down.
12631 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012632 if ((uses != NULL) && ((type->flags &
12633 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012634 cur = uses;
12635 while (cur != NULL) {
12636 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012637 while (tmp != NULL) {
12638 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012639 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012640 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012641 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12642
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012643 xmlSchemaPAttrUseErr(pctxt,
12644 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12645 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012646 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012647 xmlSchemaFormatQName(&str,
12648 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12649 xmlSchemaGetAttrName(tmp->attr)));
12650 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012651 break;
12652 }
12653 tmp = tmp->next;
12654 }
12655 cur = cur->next;
12656 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012657 }
12658 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012659 /*
12660 * Derive by restriction.
12661 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012662 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012663 type->attributeUses = uses;
12664 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012665 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012666 const xmlChar *bEffValue;
12667 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012668
12669 cur = uses;
12670 while (cur != NULL) {
12671 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012672 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012673 base = type->attributeUses;
12674 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012675 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012676 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012677 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012678 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012679
12680 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012681
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012682 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012683 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12684 (base->attr->occurs ==
12685 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12686 /*
12687 * NOOP.
12688 */
12689 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012690 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12691 (base->attr->occurs ==
12692 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012693 /*
12694 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012695 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012696 xmlSchemaPAttrUseErr(pctxt,
12697 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12698 type, cur->attr,
12699 "The 'optional' use is inconsistent with a "
12700 "matching 'required' use of the base type",
12701 NULL);
12702 } else if ((cur->attr->occurs ==
12703 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12704 (base->attr->occurs ==
12705 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12706 /*
12707 * derivation-ok-restriction 3
12708 */
12709 xmlSchemaPCustomErr(pctxt,
12710 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12711 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012712 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012713 "attribute use '%s' of the base type is "
12714 "missing",
12715 xmlSchemaFormatQName(&str,
12716 xmlSchemaGetAttrTargetNsURI(base->attr),
12717 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012718 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012719 } else if (xmlSchemaCheckCOSSTDerivedOK(
12720 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12721
12722 /*
12723 * SPEC (2.1.2) "R's {attribute declaration}'s
12724 * {type definition} must be validly derived from
12725 * B's {type definition} given the empty set as
12726 * defined in Type Derivation OK (Simple) (§3.14.6)."
12727 */
12728 xmlSchemaPAttrUseErr(pctxt,
12729 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12730 type, cur->attr,
12731 "The attribute declaration's type "
12732 "definition is not validly derived from "
12733 "the corresponding definition in the "
12734 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012735 } else {
12736 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012737 * 2.1.3 [Definition:] Let the effective value
12738 * constraint of an attribute use be its {value
12739 * constraint}, if present, otherwise its {attribute
12740 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012741 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012742 xmlSchemaGetEffectiveValueConstraint(base->attr,
12743 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012744 /*
12745 * 2.1.3 ... one of the following must be true
12746 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012747 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012748 * ·absent· or default.
12749 */
12750 if ((bEffValue != NULL) &&
12751 (effFixed == 1)) {
12752 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012753
12754 xmlSchemaGetEffectiveValueConstraint(base->attr,
12755 &effFixed, &rEffValue, 0);
12756 /*
12757 * 2.1.3.2 R's ·effective value constraint· is
12758 * fixed with the same string as B's.
12759 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012760 */
12761 if ((effFixed == 0) ||
12762 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012763 xmlSchemaPAttrUseErr(pctxt,
12764 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12765 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012766 "The effective value constraint of the "
12767 "attribute use is inconsistent with "
12768 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012769 NULL);
12770 } else {
12771 /*
12772 * Override the attribute use.
12773 */
12774 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012775 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012776 } else
12777 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012778 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012779
Daniel Veillard3646d642004-06-02 19:19:14 +000012780 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012781 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012782 base = base->next;
12783 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012784
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012785 if ((!found) && (cur->attr->occurs !=
12786 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12787 /*
12788 * derivation-ok-restriction 2.2
12789 */
12790 if ((baseType->attributeWildcard == NULL) ||
12791 (xmlSchemaCheckCVCWildcardNamespace(
12792 baseType->attributeWildcard,
12793 cur->attr->targetNamespace) != 1)) {
12794 xmlSchemaPAttrUseErr(pctxt,
12795 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12796 type, cur->attr,
12797 "Neither a matching attribute use, "
12798 "nor a matching wildcard in the base type does exist",
12799 NULL);
12800 } else {
12801 /*
12802 * Add the attribute use.
12803 *
12804 * Note that this may lead to funny derivation error reports, if
12805 * multiple equal attribute uses exist; but this is not
12806 * allowed anyway, and it will be reported beforehand.
12807 */
12808 tmp = cur;
12809 if (prev != NULL)
12810 prev->next = cur->next;
12811 else
12812 uses = cur->next;
12813 cur = cur->next;
12814 tmp->next = NULL;
12815 if (type->attributeUses == NULL) {
12816 type->attributeUses = tmp;
12817 } else
12818 lastBaseUse->next = tmp;
12819 lastBaseUse = tmp;
12820
12821 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012822 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012823 }
12824 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012825 cur = cur->next;
12826 }
12827 if (uses != NULL)
12828 xmlSchemaFreeAttributeUseList(uses);
12829 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012830 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012831 /*
12832 * The spec allows only appending, and not other kinds of extensions.
12833 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012834 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012835 */
12836 if (uses != NULL) {
12837 if (type->attributeUses == NULL) {
12838 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012839 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012840 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012841 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012842 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012843 PERROR_INT("xmlSchemaBuildAttributeValidation",
12844 "no derivation method");
12845 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012846 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012847 /*
12848 * 3.4.6 -> Complex Type Definition Properties Correct
12849 */
12850 if (type->attributeUses != NULL) {
12851 cur = type->attributeUses;
12852 prev = NULL;
12853 while (cur != NULL) {
12854 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012855 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012856 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012857 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012858 * Note that this was already done for "restriction" and types derived from
12859 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012860 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012861 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12862 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012863 while (tmp != NULL) {
12864 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012865 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012866 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012867 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012868
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012869 xmlSchemaPAttrUseErr(pctxt,
12870 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12871 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012872 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012873 break;
12874 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012875 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012876 }
12877 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012878 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012879 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012880 * not have {type definition}s which are or are derived from ID.
12881 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012882 if ((cur->attr->subtypes != NULL) &&
12883 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12884 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012885 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012886 xmlSchemaPAttrUseErr(pctxt,
12887 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12888 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012889 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012890 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012891 NULL);
12892 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012893 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012894 id = cur;
12895 }
12896 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012897 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012898 * stage is to be able to catch dublicate attribute uses. So we had to keep
12899 * prohibited uses in the list as well.
12900 */
12901 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12902 tmp = cur;
12903 if (prev == NULL)
12904 type->attributeUses = cur->next;
12905 else
12906 prev->next = cur->next;
12907 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012908 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012909 } else {
12910 prev = cur;
12911 cur = cur->next;
12912 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012913 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012914 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012915 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012916 * TODO: This check should be removed if we are 100% sure of
12917 * the base type attribute uses already being built.
12918 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012919 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012920 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012921 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012922 PERROR_INT("xmlSchemaBuildAttributeValidation",
12923 "attribute uses not builded on base type");
12924 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012925 return (0);
12926}
12927
12928/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012929 * xmlSchemaTypeFinalContains:
12930 * @schema: the schema
12931 * @type: the type definition
12932 * @final: the final
12933 *
12934 * Evaluates if a type definition contains the given "final".
12935 * This does take "finalDefault" into account as well.
12936 *
12937 * Returns 1 if the type does containt the given "final",
12938 * 0 otherwise.
12939 */
12940static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012941xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012942{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012943 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012944 return (0);
12945 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012946 return (1);
12947 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012948 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012949}
12950
12951/**
12952 * xmlSchemaGetUnionSimpleTypeMemberTypes:
12953 * @type: the Union Simple Type
12954 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012955 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012956 * returns NULL otherwise.
12957 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012958static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000012959xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
12960{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012961 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012962 if (type->memberTypes != NULL)
12963 return (type->memberTypes);
12964 else
12965 type = type->baseType;
12966 }
12967 return (NULL);
12968}
12969
12970/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012971 * xmlSchemaGetParticleTotalRangeMin:
12972 * @particle: the particle
12973 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012974 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012975 * (all and sequence) + (choice)
12976 *
12977 * Returns the minimun Effective Total Range.
12978 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012979static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012980xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012981{
12982 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012983 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012984 return (0);
12985 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012986 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012987 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012988 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012989
12990 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012991 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012992 while (part != NULL) {
12993 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
12994 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012995 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012996 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012997 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012998 if (cur == 0)
12999 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013000 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013001 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013002 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013003 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013004 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013005 } else {
13006 /* <all> and <sequence> */
13007 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013008 xmlSchemaParticlePtr part =
13009 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013010
13011 if (part == NULL)
13012 return (0);
13013 do {
13014 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13015 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013016 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013017 else
13018 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013019 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013020 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013021 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013022 }
13023}
13024
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013025/**
13026 * xmlSchemaGetParticleTotalRangeMax:
13027 * @particle: the particle
13028 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013029 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013030 * (all and sequence) + (choice)
13031 *
13032 * Returns the maximum Effective Total Range.
13033 */
13034static int
13035xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13036{
13037 if ((particle->children == NULL) ||
13038 (particle->children->children == NULL))
13039 return (0);
13040 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13041 int max = -1, cur;
13042 xmlSchemaParticlePtr part =
13043 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013044
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013045 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13046 if (part->children == NULL)
13047 continue;
13048 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13049 (part->children->type == XML_SCHEMA_TYPE_ANY))
13050 cur = part->maxOccurs;
13051 else
13052 cur = xmlSchemaGetParticleTotalRangeMax(part);
13053 if (cur == UNBOUNDED)
13054 return (UNBOUNDED);
13055 if ((max < cur) || (max == -1))
13056 max = cur;
13057 }
13058 /* TODO: Handle overflows? */
13059 return (particle->maxOccurs * max);
13060 } else {
13061 /* <all> and <sequence> */
13062 int sum = 0, cur;
13063 xmlSchemaParticlePtr part =
13064 (xmlSchemaParticlePtr) particle->children->children;
13065
13066 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13067 if (part->children == NULL)
13068 continue;
13069 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13070 (part->children->type == XML_SCHEMA_TYPE_ANY))
13071 cur = part->maxOccurs;
13072 else
13073 cur = xmlSchemaGetParticleTotalRangeMax(part);
13074 if (cur == UNBOUNDED)
13075 return (UNBOUNDED);
13076 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13077 return (UNBOUNDED);
13078 sum += cur;
13079 }
13080 /* TODO: Handle overflows? */
13081 return (particle->maxOccurs * sum);
13082 }
13083}
13084
13085/**
13086 * xmlSchemaIsParticleEmptiable:
13087 * @particle: the particle
13088 *
13089 * Schema Component Constraint: Particle Emptiable
13090 * Checks whether the given particle is emptiable.
13091 *
13092 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013093 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013094static int
13095xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13096{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013097 /*
13098 * SPEC (1) "Its {min occurs} is 0."
13099 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013100 if ((particle == NULL) || (particle->minOccurs == 0) ||
13101 (particle->children == NULL))
13102 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013103 /*
13104 * SPEC (2) "Its {term} is a group and the minimum part of the
13105 * effective total range of that group, [...] is 0."
13106 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013107 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013108 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013109 return (1);
13110 }
13111 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013112}
13113
13114/**
13115 * xmlSchemaCheckCOSSTDerivedOK:
13116 * @type: the derived simple type definition
13117 * @baseType: the base type definition
13118 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013119 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013120 * Type Derivation OK (Simple) (cos-st-derived-OK)
13121 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013122 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013123 * derived from @baseType.
13124 *
13125 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013126 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013127static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013128xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13129 xmlSchemaTypePtr baseType,
13130 int subset)
13131{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013132 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013133 * 1 They are the same type definition.
13134 * TODO: The identy check might have to be more complex than this.
13135 */
13136 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013137 return (0);
13138 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013139 * 2.1 restriction is not in the subset, or in the {final}
13140 * of its own {base type definition};
13141 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013142 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013143 (xmlSchemaTypeFinalContains(type->baseType,
13144 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13145 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013146 }
13147 /* 2.2 */
13148 if (type->baseType == baseType) {
13149 /*
13150 * 2.2.1 D's ·base type definition· is B.
13151 */
13152 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013153 }
13154 /*
13155 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13156 * and is validly derived from B given the subset, as defined by this
13157 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013158 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013159 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013160 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013161 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013162 return (0);
13163 }
13164 /*
13165 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013166 * definition·.
13167 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013168 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013169 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013170 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013171 }
13172 /*
13173 * 2.2.4 B's {variety} is union and D is validly derived from a type
13174 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013175 * defined by this constraint.
13176 *
13177 * NOTE: This seems not to involve built-in types, since there is no
13178 * built-in Union Simple Type.
13179 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013180 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013181 xmlSchemaTypeLinkPtr cur;
13182
13183 cur = baseType->memberTypes;
13184 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013185 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013186 return (0);
13187 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013188 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013189 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013190
Daniel Veillard01fa6152004-06-29 17:04:39 +000013191 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13192}
13193
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013194/**
13195 * xmlSchemaCheckTypeDefCircularInternal:
13196 * @pctxt: the schema parser context
13197 * @ctxtType: the type definition
13198 * @ancestor: an ancestor of @ctxtType
13199 *
13200 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013201 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013202 *
13203 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13204 * circular, 0 otherwise.
13205 */
13206static int
13207xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13208 xmlSchemaTypePtr ctxtType,
13209 xmlSchemaTypePtr ancestor)
13210{
13211 int ret;
13212
13213 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13214 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013215
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013216 if (ctxtType == ancestor) {
13217 xmlSchemaPCustomErr(pctxt,
13218 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13219 NULL, ctxtType, GET_NODE(ctxtType),
13220 "The definition is circular", NULL);
13221 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13222 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013223 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13224 /*
13225 * Avoid inifinite recursion on circular types not yet checked.
13226 */
13227 return (0);
13228 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013229 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13230 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13231 ancestor->baseType);
13232 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13233 return (ret);
13234}
13235
13236/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013237 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013238 * @item: the complex/simple type definition
13239 * @ctxt: the parser context
13240 * @name: the name
13241 *
13242 * Checks for circular type definitions.
13243 */
13244static void
13245xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013246 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013247 const xmlChar * name ATTRIBUTE_UNUSED)
13248{
13249 if ((item == NULL) ||
13250 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13251 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13252 return;
13253 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13254
13255}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013256
13257/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013258 * xmlSchemaResolveTypeDefs:
13259 * @item: the complex/simple type definition
13260 * @ctxt: the parser context
13261 * @name: the name
13262 *
13263 * Checks for circular type definitions.
13264 */
13265static void
13266xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013267 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013268 const xmlChar * name ATTRIBUTE_UNUSED)
13269{
13270 if (typeDef == NULL)
13271 return;
13272
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013273 /*
13274 * Resolve the base type.
13275 */
13276 if (typeDef->baseType == NULL) {
13277 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13278 typeDef->base, typeDef->baseNs);
13279 if (typeDef->baseType == NULL) {
13280 xmlSchemaPResCompAttrErr(ctxt,
13281 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013282 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013283 "base", typeDef->base, typeDef->baseNs,
13284 XML_SCHEMA_TYPE_SIMPLE, NULL);
13285 return;
13286 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013287 }
13288 if (IS_SIMPLE_TYPE(typeDef)) {
13289 if (VARIETY_UNION(typeDef)) {
13290 /*
13291 * Resolve the memberTypes.
13292 */
13293 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13294 return;
13295 } else if (VARIETY_LIST(typeDef)) {
13296 /*
13297 * Resolve the itemType.
13298 */
13299 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13300 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13301 typeDef->ref, typeDef->refNs);
13302 if ((typeDef->subtypes == NULL) ||
13303 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13304 typeDef->subtypes = NULL;
13305 xmlSchemaPResCompAttrErr(ctxt,
13306 XML_SCHEMAP_SRC_RESOLVE,
13307 typeDef, typeDef->node,
13308 "itemType", typeDef->ref, typeDef->refNs,
13309 XML_SCHEMA_TYPE_SIMPLE, NULL);
13310 }
13311 }
13312 return;
13313 }
13314 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013315}
13316
13317
13318
13319/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013320 * xmlSchemaCheckSTPropsCorrect:
13321 * @ctxt: the schema parser context
13322 * @type: the simple type definition
13323 *
13324 * Checks st-props-correct.
13325 *
13326 * Returns 0 if the properties are correct,
13327 * if not, a positive error code and -1 on internal
13328 * errors.
13329 */
13330static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013331xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013332 xmlSchemaTypePtr type)
13333{
13334 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13335 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013336 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013337
Daniel Veillardc0826a72004-08-10 14:17:33 +000013338 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013339 /*
13340 * Schema Component Constraint: Simple Type Definition Properties Correct
13341 *
13342 * NOTE: This is somehow redundant, since we actually built a simple type
13343 * to have all the needed information; this acts as an self test.
13344 */
13345 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13346 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013347 /* Base type: If the datatype has been ·derived· by ·restriction·
13348 * then the Simple Type Definition component from which it is ·derived·,
13349 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013350 */
13351 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013352 /*
13353 * TODO: Think about: "modulo the impact of Missing
13354 * Sub-components (§5.3)."
13355 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013356 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013357 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013358 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013359 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013360 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013361
Daniel Veillard01fa6152004-06-29 17:04:39 +000013362 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013363 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013364 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013365 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013366 NULL, type, NULL,
13367 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013368 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013369 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013370 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13371 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013372 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13373 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13374 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013375 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013376 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013377 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013378 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013379 "the simple ur-type definition as base type, not '%s'",
13380 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013381 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013382 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13383 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013384 /*
13385 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013386 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013387 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13388 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013389 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013390 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013391 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013392 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013393 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13394 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013395 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013396
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013397 /*
13398 * 3 The {final} of the {base type definition} must not contain restriction.
13399 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013400 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013401 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13402 xmlSchemaPCustomErr(ctxt,
13403 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013404 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013405 "The 'final' of its base type '%s' must not contain "
13406 "'restriction'",
13407 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013408 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013409 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013410 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013411
13412 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013413 * 2 All simple type definitions must be derived ultimately from the ·simple
13414 * ur-type definition (so· circular definitions are disallowed). That is, it
13415 * must be possible to reach a built-in primitive datatype or the ·simple
13416 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013417 *
13418 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013419 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013420 return (0);
13421}
13422
13423/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013424 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013425 * @ctxt: the schema parser context
13426 * @type: the simple type definition
13427 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013428 * Schema Component Constraint:
13429 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13430
13431 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013432 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013433 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013434 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013435 * a positive error code otherwise.
13436 */
13437static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013438xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013439 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013440{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013441 xmlChar *str = NULL;
13442
Daniel Veillard01fa6152004-06-29 17:04:39 +000013443 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013444 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13445 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013446 return (-1);
13447 }
13448
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013449 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013450 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013451 /*
13452 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013453 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013454 */
13455 if (! VARIETY_ATOMIC(type->baseType)) {
13456 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013457 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013458 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013459 "The base type '%s' is not an atomic simple type",
13460 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013461 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013462 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13463 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013464 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013465 * restriction.
13466 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013467 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013468 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013469 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013470 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013471 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013472 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013473 "The final of its base type '%s' must not contain 'restriction'",
13474 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013475 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013476 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13477 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013478
13479 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013480 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013481 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013482 * Primitive datatypes.
13483 */
13484 if (type->facets != NULL) {
13485 xmlSchemaFacetPtr facet;
13486 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013487
Daniel Veillard01fa6152004-06-29 17:04:39 +000013488 primitive = xmlSchemaGetPrimitiveType(type);
13489 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013490 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13491 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013492 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013493 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013494 facet = type->facets;
13495 do {
13496 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013497 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013498 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013499 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013500 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013501 }
13502 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013503 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013504 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013505 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013506 }
13507 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013508 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13509 * of the {base type definition} (call this BF),then the DF's {value}
13510 * must be a valid restriction of BF's {value} as defined in
13511 * [XML Schemas: Datatypes]."
13512 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013513 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013514 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013516 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013517 xmlSchemaTypePtr itemType = NULL;
13518
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013519 itemType = type->subtypes;
13520 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013521 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13522 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013523 return (-1);
13524 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013525 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013526 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013527 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013528 * 2.1 The {item type definition} must have a {variety} of atomic or
13529 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013530 * must be atomic).
13531 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013532 if ((! VARIETY_ATOMIC(itemType)) &&
13533 (! VARIETY_UNION(itemType))) {
13534 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013535 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013536 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013537 "The item type '%s' does not have a variety of atomic or union",
13538 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013539 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013540 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013541 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013542 xmlSchemaTypeLinkPtr member;
13543
13544 member = itemType->memberTypes;
13545 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013546 if (! VARIETY_ATOMIC(member->type)) {
13547 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013548 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013549 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013550 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013551 "member type '%s' of this item type is not atomic",
13552 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013553 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013554 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13555 }
13556 member = member->next;
13557 }
13558 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013559
13560 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013561 xmlSchemaFacetPtr facet;
13562 /*
13563 * This is the case if we have: <simpleType><list ..
13564 */
13565 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013566 * 2.3.1
13567 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013568 * contain list.
13569 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013570 if (xmlSchemaTypeFinalContains(itemType,
13571 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13572 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013573 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013574 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013575 "The final of its item type '%s' must not contain 'list'",
13576 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013577 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013578 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13579 }
13580 /*
13581 * 2.3.1.2 The {facets} must only contain the whiteSpace
13582 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013583 * OPTIMIZE TODO: the S4S already disallows any facet
13584 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013585 */
13586 if (type->facets != NULL) {
13587 facet = type->facets;
13588 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013589 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013590 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013591 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013592 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013593 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13594 }
13595 facet = facet->next;
13596 } while (facet != NULL);
13597 }
13598 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013599 * MAYBE TODO: (Hmm, not really) Datatypes states:
13600 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13601 * whose ·lexical space· allows space (such as string or anyURI)or
13602 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013603 * ·lexical space· allows space.
13604 */
13605 } else {
13606 /*
13607 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013608 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013609 */
13610 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013611 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013612 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13613 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013614 if (! VARIETY_LIST(type->baseType)) {
13615 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013616 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013617 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013618 "The base type '%s' must be a list type",
13619 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013620 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013621 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13622 }
13623 /*
13624 * 2.3.2.2 The {final} of the {base type definition} must not
13625 * contain restriction.
13626 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013627 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013628 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013629 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013630 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013631 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013632 "The 'final' of the base type '%s' must not contain 'restriction'",
13633 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013634 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013635 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13636 }
13637 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013638 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013639 * from the {base type definition}'s {item type definition} given
13640 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13641 */
13642 {
13643 xmlSchemaTypePtr baseItemType;
13644
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013645 baseItemType = type->baseType->subtypes;
13646 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013647 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13648 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013649 return (-1);
13650 }
13651 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013652 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13653 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013654 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013655 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013656 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013657 NULL, type, NULL,
13658 "The item type '%s' is not validly derived from "
13659 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013660 xmlSchemaGetComponentQName(&str, itemType),
13661 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13662 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013663
13664 FREE_AND_NULL(str)
13665 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013666 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013667 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13668 }
13669 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013670
Daniel Veillard01fa6152004-06-29 17:04:39 +000013671 if (type->facets != NULL) {
13672 xmlSchemaFacetPtr facet;
13673 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013674 /*
13675 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013676 * and enumeration facet components are allowed among the {facets}.
13677 */
13678 facet = type->facets;
13679 do {
13680 switch (facet->type) {
13681 case XML_SCHEMA_FACET_LENGTH:
13682 case XML_SCHEMA_FACET_MINLENGTH:
13683 case XML_SCHEMA_FACET_MAXLENGTH:
13684 case XML_SCHEMA_FACET_WHITESPACE:
13685 /*
13686 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013687 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013688 */
13689 case XML_SCHEMA_FACET_PATTERN:
13690 case XML_SCHEMA_FACET_ENUMERATION:
13691 break;
13692 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013693 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013694 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013695 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013696 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013697 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013698 * invalid facets.
13699 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013700 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013701 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013702 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013703 facet = facet->next;
13704 } while (facet != NULL);
13705 if (ok == 0)
13706 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13707 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013708 * SPEC (2.3.2.5) (same as 1.3.2)
13709 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013710 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013711 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013712 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013713 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013714 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013715 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013716 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013717 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013718 * atomic or list.
13719 */
13720 xmlSchemaTypeLinkPtr member;
13721
13722 member = type->memberTypes;
13723 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013724 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013725 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013726
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013727 if ((! VARIETY_ATOMIC(member->type)) &&
13728 (! VARIETY_LIST(member->type))) {
13729 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013730 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013731 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013732 "The member type '%s' is neither an atomic, nor a list type",
13733 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013734 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013735 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13736 }
13737 member = member->next;
13738 }
13739 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013740 * 3.3.1 If the {base type definition} is the ·simple ur-type
13741 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013742 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013743 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013744 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013745 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013746 * {final} which does not contain union.
13747 */
13748 member = type->memberTypes;
13749 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013750 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013751 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013752 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013753 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013754 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013755 "The 'final' of member type '%s' contains 'union'",
13756 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013757 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013758 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13759 }
13760 member = member->next;
13761 }
13762 /*
13763 * 3.3.1.2 The {facets} must be empty.
13764 */
13765 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013766 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013767 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013768 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013769 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013770 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13771 }
13772 } else {
13773 /*
13774 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013775 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013776 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013777 if (! VARIETY_UNION(type->baseType)) {
13778 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013779 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013780 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013781 "The base type '%s' is not a union type",
13782 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013783 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013784 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13785 }
13786 /*
13787 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13788 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013789 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013790 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013791 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013792 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013793 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013794 "The 'final' of its base type '%s' must not contain 'restriction'",
13795 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013796 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013797 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13798 }
13799 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013800 * 3.3.2.3 The {member type definitions}, in order, must be validly
13801 * derived from the corresponding type definitions in the {base
13802 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013803 * as defined in Type Derivation OK (Simple) (§3.14.6).
13804 */
13805 {
13806 xmlSchemaTypeLinkPtr baseMember;
13807
13808 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013809 * OPTIMIZE: if the type is restricting, it has no local defined
13810 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013811 * thus a check for equality can be skipped.
13812 */
13813 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013814 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013815 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013816 * types of it's base type. This check seems not necessary with
13817 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013818 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013819 */
13820 if (type->memberTypes != NULL) {
13821 member = type->memberTypes;
13822 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013823 if ((member == NULL) && (baseMember != NULL)) {
13824 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13825 "different number of member types in base");
13826 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013827 while (member != NULL) {
13828 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013829 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13830 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013831 }
13832 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013833 (xmlSchemaCheckCOSSTDerivedOK(
13834 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013835 xmlChar *strBMT = NULL, *strBT = NULL;
13836
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013837 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013838 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13839 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013840 "The member type %s is not validly "
13841 "derived from its corresponding member "
13842 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013843 xmlSchemaGetComponentQName(&str, member->type),
13844 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13845 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013846 FREE_AND_NULL(str)
13847 FREE_AND_NULL(strBMT)
13848 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013849 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013850 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013851 member = member->next;
13852 baseMember = baseMember->next;
13853 }
13854 }
13855 }
13856 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013857 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013858 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013859 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013860 if (type->facets != NULL) {
13861 xmlSchemaFacetPtr facet;
13862 int ok = 1;
13863
13864 facet = type->facets;
13865 do {
13866 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13867 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013868 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013869 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013870 NULL, type, facet);
13871 ok = 0;
13872 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013873 facet = facet->next;
13874 } while (facet != NULL);
13875 if (ok == 0)
13876 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013877
Daniel Veillard01fa6152004-06-29 17:04:39 +000013878 }
13879 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013880 * SPEC (3.3.2.5) (same as 1.3.2)
13881 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013882 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013883 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013884 */
13885 }
13886 }
13887
13888 return (0);
13889}
13890
13891/**
13892 * xmlSchemaCheckSRCSimpleType:
13893 * @ctxt: the schema parser context
13894 * @type: the simple type definition
13895 *
13896 * Checks crc-simple-type constraints.
13897 *
13898 * Returns 0 if the constraints are satisfied,
13899 * if not a positive error code and -1 on internal
13900 * errors.
13901 */
13902static int
13903xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13904 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013905{
13906 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013907 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013908 * must satisfy the conditions set out in Constraints on Simple Type
13909 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013910 */
13911 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13912 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13913 /*
13914 * TODO: Removed this, since it got annoying to get an
13915 * extra error report, if anything failed until now.
13916 * Enable this if needed.
13917 */
13918 /*
13919 xmlSchemaPErr(ctxt, type->node,
13920 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013921 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013922 "on simple type definitions.\n",
13923 type->name, NULL);
13924 */
13925 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13926 }
13927
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013928 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013929 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013930 * src-simple-type.2 If the <restriction> alternative is chosen,
13931 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013932 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013933 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013934 /*
13935 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013936 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013937 */
13938 } else if (VARIETY_LIST(type)) {
13939 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13940 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013941 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013942 *
13943 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013944 */
13945 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013946 xmlSchemaTypeLinkPtr member;
13947 xmlSchemaTypePtr ancestor, anySimpleType;
13948
13949 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13950
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013951 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
13952 * the <union> alternative is chosen, there must not be any entries
13953 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000013954 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013955 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013956 member = type->memberTypes;
13957 while (member != NULL) {
13958 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013959 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013960 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013961 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013962 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013963 NULL, type, NULL,
13964 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013965 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013966 }
13967 if (IS_NOT_TYPEFIXED(ancestor))
13968 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013969 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013970 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000013971 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013972 * type as item type, which in turn has a list ST as member
13973 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000013974 * was not yet performed.
13975 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013976 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013977
Daniel Veillard01fa6152004-06-29 17:04:39 +000013978 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013979 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013980 member = member->next;
13981 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013982 }
13983
13984 return (0);
13985}
13986
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013987static int
13988xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
13989{
13990 if (ctxt->vctxt == NULL) {
13991 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
13992 if (ctxt->vctxt == NULL) {
13993 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013994 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013995 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013996 "failed to create a temp. validation context.\n",
13997 NULL, NULL);
13998 return (-1);
13999 }
14000 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014001 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014002 }
14003 return (0);
14004}
14005
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014006static int
14007xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14008 xmlNodePtr node,
14009 xmlSchemaTypePtr type,
14010 const xmlChar *value,
14011 xmlSchemaValPtr *retVal,
14012 int fireErrors,
14013 int normalize,
14014 int isNormalized);
14015
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014016/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014017 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014018 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014019 * @type: the simple type definition
14020 * @value: the default value
14021 * @node: an optional node (the holder of the value)
14022 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014023 * Schema Component Constraint: Element Default Valid (Immediate)
14024 * (cos-valid-default)
14025 * This will be used by the parser only. For the validator there's
14026 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014027 *
14028 * Returns 0 if the constraints are satisfied,
14029 * if not, a positive error code and -1 on internal
14030 * errors.
14031 */
14032static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014033xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14034 xmlNodePtr node,
14035 xmlSchemaTypePtr type,
14036 const xmlChar *value,
14037 xmlSchemaValPtr *val)
14038{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014039 int ret = 0;
14040
14041 /*
14042 * cos-valid-default:
14043 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014044 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014045 * definition the appropriate case among the following must be true:
14046 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014047 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014048 /*
14049 * Complex type.
14050 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014051 * SPEC (2.1) "its {content type} must be a simple type definition
14052 * or mixed."
14053 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014054 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014055 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014056 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014057 if ((! HAS_SIMPLE_CONTENT(type)) &&
14058 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14059 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014060 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014061 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014062 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014063 "For a string to be a valid default, the type definition "
14064 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014065 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014066 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14067 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014068 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014069 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014070 * 1 If the type definition is a simple type definition, then the string
14071 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014072 * Valid (§3.14.4).
14073 *
14074 * AND
14075 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014076 * 2.2.1 If the {content type} is a simple type definition, then the
14077 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014078 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014079 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014080 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014081 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14082 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014083 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014084 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14085 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014086 else
14087 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014088
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014089 if (ret < 0) {
14090 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14091 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014092 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014093
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014094 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014095}
14096
14097/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014098 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014099 * @ctxt: the schema parser context
14100 * @type: the complex type definition
14101 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014102 *.(4.6) Constraints on Complex Type Definition Schema Components
14103 * Schema Component Constraint:
14104 * Complex Type Definition Properties Correct (ct-props-correct)
14105 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014106 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014107 * Returns 0 if the constraints are satisfied, a positive
14108 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014109 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014110static int
14111xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14112 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014113{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014114 /*
14115 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14116 *
14117 * SPEC (1) "The values of the properties of a complex type definition must
14118 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014119 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014120 * Sub-components (§5.3)."
14121 */
14122 if ((type->baseType != NULL) &&
14123 (IS_SIMPLE_TYPE(type->baseType)) &&
14124 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14125 /*
14126 * SPEC (2) "If the {base type definition} is a simple type definition,
14127 * the {derivation method} must be extension."
14128 */
14129 xmlSchemaPCustomErr(pctxt,
14130 XML_SCHEMAP_SRC_CT_1,
14131 NULL, type, NULL,
14132 "If the base type is a simple type, the derivation method must be "
14133 "'extension'", NULL);
14134 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014135 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014136 /*
14137 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14138 * definition·. That is, it must be possible to reach the ·ur-type
14139 * definition by repeatedly following the {base type definition}."
14140 *
14141 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14142 *
14143 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014144 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014145 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14146 * must not have {type definition}s which are or are derived from ID."
14147 *
14148 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14149 */
14150 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014151}
14152
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014153static int
14154xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14155 xmlSchemaTypePtr typeB)
14156{
14157 /*
14158 * TODO: This should implement component-identity
14159 * in the future.
14160 */
14161 if ((typeA == NULL) || (typeB == NULL))
14162 return (0);
14163 return (typeA == typeB);
14164}
14165
14166/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014167 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014168 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014169 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014170 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014171 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014172 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014173 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014174 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14175 *
14176 * STATUS: completed
14177 *
14178 * Returns 0 if the constraints are satisfied, or 1
14179 * if not.
14180 */
14181static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014182xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014183 xmlSchemaTypePtr baseType,
14184 int set)
14185{
14186 int equal = xmlSchemaAreEqualTypes(type, baseType);
14187 /* TODO: Error codes. */
14188 /*
14189 * SPEC "For a complex type definition (call it D, for derived)
14190 * to be validly derived from a type definition (call this
14191 * B, for base) given a subset of {extension, restriction}
14192 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014193 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014194 if (! equal) {
14195 /*
14196 * SPEC (1) "If B and D are not the same type definition, then the
14197 * {derivation method} of D must not be in the subset."
14198 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014199 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014200 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014201 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014202 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014203 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014204 } else {
14205 /*
14206 * SPEC (2.1) "B and D must be the same type definition."
14207 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014208 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014209 }
14210 /*
14211 * SPEC (2.2) "B must be D's {base type definition}."
14212 */
14213 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014214 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014215 /*
14216 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14217 * definition·."
14218 */
14219 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014220 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014221
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014222 if (IS_COMPLEX_TYPE(type->baseType)) {
14223 /*
14224 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14225 * must be validly derived from B given the subset as defined by this
14226 * constraint."
14227 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014228 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014229 baseType, set));
14230 } else {
14231 /*
14232 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14233 * must be validly derived from B given the subset as defined in Type
14234 * Derivation OK (Simple) (§3.14.6).
14235 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014236 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14237 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014238}
14239
14240/**
14241 * xmlSchemaCheckCOSDerivedOK:
14242 * @type: the derived simple type definition
14243 * @baseType: the base type definition
14244 *
14245 * Calls:
14246 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014247 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014248 * Checks wheter @type can be validly derived from @baseType.
14249 *
14250 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014251 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014252static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014253xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014254 xmlSchemaTypePtr baseType,
14255 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014256{
14257 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014258 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014259 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014260 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014261}
14262
William M. Brack2f2a6632004-08-20 23:09:47 +000014263/**
14264 * xmlSchemaCheckCOSCTExtends:
14265 * @ctxt: the schema parser context
14266 * @type: the complex type definition
14267 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014268 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014269 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014270 * Derivation Valid (Extension) (cos-ct-extends)
14271 *
14272 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014273 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014274 * (1.5)
14275 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014276 *
14277 * Returns 0 if the constraints are satisfied, a positive
14278 * error code if not and -1 if an internal error occured.
14279 */
14280static int
14281xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14282 xmlSchemaTypePtr type)
14283{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014284 xmlSchemaTypePtr base = type->baseType;
14285 /*
14286 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14287 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014288 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014289 /*
14290 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014291 * then all of the following must be true:"
14292 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014293 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14294 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014295 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014296 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014297 */
14298 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14299 xmlSchemaPCustomErr(ctxt,
14300 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14301 NULL, type, NULL,
14302 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014303 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014304 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14305 }
14306 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014307 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014308 * uses}
14309 * of the complex type definition itself, that is, for every attribute
14310 * use in the {attribute uses} of the {base type definition}, there
14311 * must be an attribute use in the {attribute uses} of the complex
14312 * type definition itself whose {attribute declaration} has the same
14313 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014314 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014315 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014316 * NOTE (1.2): This will be already satisfied by the way the attribute
14317 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14318 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014319 */
14320
14321 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014322 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14323 * definition must also have one, and the base type definition's
14324 * {attribute wildcard}'s {namespace constraint} must be a subset
14325 * of the complex type definition's {attribute wildcard}'s {namespace
14326 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014327 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014328 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014329 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014330 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014331 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014332 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014333 if ((type->contentTypeDef != NULL) &&
14334 (type->contentTypeDef == base->contentTypeDef)) {
14335 /*
14336 * SPEC (1.4.1) "The {content type} of the {base type definition}
14337 * and the {content type} of the complex type definition itself
14338 * must be the same simple type definition"
14339 * PASS
14340 */
14341 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14342 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14343 /*
14344 * SPEC (1.4.2) "The {content type} of both the {base type
14345 * definition} and the complex type definition itself must
14346 * be empty."
14347 * PASS
14348 */
14349 } else {
14350 /*
14351 * SPEC (1.4.3) "All of the following must be true:"
14352 */
14353 if (type->subtypes == NULL) {
14354 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014355 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014356 * definition itself must specify a particle.
14357 */
14358 xmlSchemaPCustomErr(ctxt,
14359 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14360 NULL, type, NULL,
14361 "The content type must specify a particle", NULL);
14362 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14363 }
14364 /*
14365 * SPEC (1.4.3.2) "One of the following must be true:"
14366 */
14367 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14368 /*
14369 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14370 * definition} must be empty.
14371 * PASS
14372 */
14373 } else {
14374 /*
14375 * SPEC (1.4.3.2.2) "All of the following must be true:"
14376 */
14377 if ((type->contentType != base->contentType) ||
14378 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14379 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14380 /*
14381 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14382 * or both must be element-only."
14383 */
14384 xmlSchemaPCustomErr(ctxt,
14385 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14386 NULL, type, NULL,
14387 "The content type of both, the type and its base "
14388 "type, must either 'mixed' or 'element-only'", NULL);
14389 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014390 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014391 /*
14392 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14393 * complex type definition must be a ·valid extension·
14394 * of the {base type definition}'s particle, as defined
14395 * in Particle Valid (Extension) (§3.9.6)."
14396 *
14397 * NOTE that we won't check "Particle Valid (Extension)",
14398 * since it is ensured by the derivation process in
14399 * xmlSchemaTypeFixup(). We need to implement this when heading
14400 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014401 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014402 }
14403 /*
14404 * TODO (1.5)
14405 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014406 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014407 } else {
14408 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014409 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014410 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014411 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014412 if (type->contentTypeDef != base) {
14413 /*
14414 * SPEC (2.1) "The {content type} must be the same simple type
14415 * definition."
14416 */
14417 xmlSchemaPCustomErr(ctxt,
14418 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14419 NULL, type, NULL,
14420 "The content type must be the simple base type", NULL);
14421 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14422 }
14423 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14424 /*
14425 * SPEC (2.2) "The {final} of the {base type definition} must not
14426 * contain extension"
14427 * NOTE that this is the same as (1.1).
14428 */
14429 xmlSchemaPCustomErr(ctxt,
14430 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14431 NULL, type, NULL,
14432 "The 'final' of the base type definition "
14433 "contains 'extension'", NULL);
14434 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014435 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014436 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014437 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014438}
14439
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014440/**
14441 * xmlSchemaCheckDerivationOKRestriction:
14442 * @ctxt: the schema parser context
14443 * @type: the complex type definition
14444 *
14445 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014446 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014447 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14448 *
14449 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014450 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014451 * (5.4.2), (5.2.2.1)
14452 *
14453 * Returns 0 if the constraints are satisfied, a positive
14454 * error code if not and -1 if an internal error occured.
14455 */
14456static int
14457xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14458 xmlSchemaTypePtr type)
14459{
14460 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014461
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014462 /*
14463 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14464 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014465 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014466 base = type->baseType;
14467 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14468 /*
14469 * SPEC (1) "The {base type definition} must be a complex type
14470 * definition whose {final} does not contain restriction."
14471 */
14472 xmlSchemaPCustomErr(ctxt,
14473 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14474 NULL, type, NULL,
14475 "The 'final' of the base type definition "
14476 "contains 'restriction'", NULL);
14477 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14478 }
14479 /*
14480 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14481 *
14482 * SPEC (5) "One of the following must be true:"
14483 */
14484 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14485 /*
14486 * SPEC (5.1) "The {base type definition} must be the
14487 * ·ur-type definition·."
14488 * PASS
14489 */
14490 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14491 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14492 /*
14493 * SPEC (5.2.1) "The {content type} of the complex type definition
14494 * must be a simple type definition"
14495 *
14496 * SPEC (5.2.2) "One of the following must be true:"
14497 */
14498 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14499 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14500 /*
14501 * SPEC (5.2.2.1) "The {content type} of the {base type
14502 * definition} must be a simple type definition from which
14503 * the {content type} is validly derived given the empty
14504 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14505 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014506 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014507 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14508 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014509 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014510 /*
14511 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14512 * and have a particle which is ·emptiable· as defined in
14513 * Particle Emptiable (§3.9.6)."
14514 * PASS
14515 */
14516 } else {
14517 xmlSchemaPCustomErr(ctxt,
14518 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14519 NULL, type, NULL,
14520 "The content type of the base type must be either "
14521 "a simple type or 'mixed' and an emptiable particle", NULL);
14522 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14523 }
14524 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14525 /*
14526 * SPEC (5.3.1) "The {content type} of the complex type itself must
14527 * be empty"
14528 */
14529 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14530 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014531 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014532 * definition} must also be empty."
14533 * PASS
14534 */
14535 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14536 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14537 xmlSchemaIsParticleEmptiable(
14538 (xmlSchemaParticlePtr) base->subtypes)) {
14539 /*
14540 * SPEC (5.3.2.2) "The {content type} of the {base type
14541 * definition} must be elementOnly or mixed and have a particle
14542 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14543 * PASS
14544 */
14545 } else {
14546 xmlSchemaPCustomErr(ctxt,
14547 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14548 NULL, type, NULL,
14549 "The content type of the base type must be either "
14550 "empty or 'mixed' (or 'elements-only') and an emptiable "
14551 "particle", NULL);
14552 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14553 }
14554 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014555 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014556 /*
14557 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14558 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014559 */
14560 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14561 /*
14562 * SPEC (5.4.1.2) "The {content type} of the complex type
14563 * definition itself and of the {base type definition} must be
14564 * mixed"
14565 */
14566 xmlSchemaPCustomErr(ctxt,
14567 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14568 NULL, type, NULL,
14569 "If the content type is 'mixed', then the content type of the "
14570 "base type must also be 'mixed'", NULL);
14571 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14572 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014573 /*
14574 * SPEC (5.4.2) "The particle of the complex type definition itself
14575 * must be a ·valid restriction· of the particle of the {content
14576 * type} of the {base type definition} as defined in Particle Valid
14577 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014578 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014579 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014580 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014581 } else {
14582 xmlSchemaPCustomErr(ctxt,
14583 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14584 NULL, type, NULL,
14585 "The type is not a valid restriction of its base type", NULL);
14586 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14587 }
14588 return (0);
14589}
14590
14591/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014592 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014593 * @ctxt: the schema parser context
14594 * @type: the complex type definition
14595 *
14596 * (3.4.6) Constraints on Complex Type Definition Schema Components
14597 *
14598 * Returns 0 if the constraints are satisfied, a positive
14599 * error code if not and -1 if an internal error occured.
14600 */
14601static int
14602xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14603 xmlSchemaTypePtr type)
14604{
14605 int ret;
14606 /*
14607 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014608 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014609 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14610 if (ret != 0)
14611 return (ret);
14612 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14613 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14614 else
14615 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14616 return (ret);
14617}
14618
14619/**
14620 * xmlSchemaCheckSRCCT:
14621 * @ctxt: the schema parser context
14622 * @type: the complex type definition
14623 *
14624 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014625 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014626 * Complex Type Definition Representation OK (src-ct)
14627 *
14628 * Returns 0 if the constraints are satisfied, a positive
14629 * error code if not and -1 if an internal error occured.
14630 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014631static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014632xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014633 xmlSchemaTypePtr type)
14634{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014635 xmlSchemaTypePtr base;
14636 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014637
14638 /*
14639 * TODO: Adjust the error codes here, as I used
14640 * XML_SCHEMAP_SRC_CT_1 only yet.
14641 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014642 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014643 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014644 /*
14645 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014646 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014647 * must be a complex type definition;
14648 */
14649 if (! IS_COMPLEX_TYPE(base)) {
14650 xmlChar *str = NULL;
14651 xmlSchemaPCustomErr(ctxt,
14652 XML_SCHEMAP_SRC_CT_1,
14653 NULL, type, type->node,
14654 "If using <complexContent>, the base type is expected to be "
14655 "a complex type. The base type '%s' is a simple type",
14656 xmlSchemaFormatQName(&str, base->targetNamespace,
14657 base->name));
14658 FREE_AND_NULL(str)
14659 return (XML_SCHEMAP_SRC_CT_1);
14660 }
14661 } else {
14662 /*
14663 * SPEC
14664 * 2 If the <simpleContent> alternative is chosen, all of the
14665 * following must be true:
14666 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14667 * base [attribute] must be one of the following:
14668 */
14669 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014670 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014671 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14672 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014673 /*
14674 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014675 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014676 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014677 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014678 xmlSchemaPCustomErr(ctxt,
14679 XML_SCHEMAP_SRC_CT_1,
14680 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014681 "If using <simpleContent> and <restriction>, the base "
14682 "type must be a complex type. The base type '%s' is "
14683 "a simple type",
14684 xmlSchemaFormatQName(&str, base->targetNamespace,
14685 base->name));
14686 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014687 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014688 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014689 } else {
14690 /* Base type is a complex type. */
14691 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14692 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14693 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014694 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014695 * simple type definition;
14696 * PASS
14697 */
14698 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014699 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014700 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014701 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014702 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014703 type->name);
14704 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014705 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014706 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14707 (type->flags &
14708 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014709
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014710 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014711 * 2.1.2 only if the <restriction> alternative is also
14712 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014713 * is mixed and a particle emptiable.
14714 */
14715 if (! xmlSchemaIsParticleEmptiable(
14716 (xmlSchemaParticlePtr) base->subtypes)) {
14717 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014718 } else
14719 /*
14720 * Attention: at this point the <simpleType> child is in
14721 * ->contentTypeDef (put there during parsing).
14722 */
14723 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014724 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014725 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014726 * 2.2 If clause 2.1.2 above is satisfied, then there
14727 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014728 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014729 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014730 /* TODO: Change error code to ..._SRC_CT_2_2. */
14731 xmlSchemaPCustomErr(ctxt,
14732 XML_SCHEMAP_SRC_CT_1,
14733 NULL, type, NULL,
14734 "A <simpleType> is expected among the children "
14735 "of <restriction>, if <simpleContent> is used and "
14736 "the base type '%s' is a complex type",
14737 xmlSchemaFormatQName(&str, base->targetNamespace,
14738 base->name));
14739 FREE_AND_NULL(str)
14740 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014741 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014742 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014743 ret = XML_SCHEMAP_SRC_CT_1;
14744 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014745 }
14746 if (ret > 0) {
14747 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014748 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014749 xmlSchemaPCustomErr(ctxt,
14750 XML_SCHEMAP_SRC_CT_1,
14751 NULL, type, NULL,
14752 "If <simpleContent> and <restriction> is used, the "
14753 "base type must be a simple type or a complex type with "
14754 "mixed content and particle emptiable. The base type "
14755 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014756 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014757 base->name));
14758 } else {
14759 xmlSchemaPCustomErr(ctxt,
14760 XML_SCHEMAP_SRC_CT_1,
14761 NULL, type, NULL,
14762 "If <simpleContent> and <extension> is used, the "
14763 "base type must be a simple type. The base type '%s' "
14764 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014765 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014766 base->name));
14767 }
14768 FREE_AND_NULL(str)
14769 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014770 }
14771 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014772 * SPEC (3) "The corresponding complex type definition component must
14773 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014774 * Definition Schema Components (§3.4.6);"
14775 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014776 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014777 /*
14778 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014779 * above for {attribute wildcard} is satisfied, the intensional
14780 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014781 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014782 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014783 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014784 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014785}
William M. Brack2f2a6632004-08-20 23:09:47 +000014786
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014787#ifdef ENABLE_PARTICLE_RESTRICTION
14788/**
14789 * xmlSchemaCheckParticleRangeOK:
14790 * @ctxt: the schema parser context
14791 * @type: the complex type definition
14792 *
14793 * (3.9.6) Constraints on Particle Schema Components
14794 * Schema Component Constraint:
14795 * Occurrence Range OK (range-ok)
14796 *
14797 * STATUS: complete
14798 *
14799 * Returns 0 if the constraints are satisfied, a positive
14800 * error code if not and -1 if an internal error occured.
14801 */
14802static int
14803xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14804 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014805{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014806 if (rmin < bmin)
14807 return (1);
14808 if ((bmax != UNBOUNDED) &&
14809 (rmax > bmax))
14810 return (1);
14811 return (0);
14812}
14813
14814/**
14815 * xmlSchemaCheckRCaseNameAndTypeOK:
14816 * @ctxt: the schema parser context
14817 * @r: the restricting element declaration particle
14818 * @b: the base element declaration particle
14819 *
14820 * (3.9.6) Constraints on Particle Schema Components
14821 * Schema Component Constraint:
14822 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14823 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014824 *
14825 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014826 * MISSING (3.2.3)
14827 * CLARIFY: (3.2.2)
14828 *
14829 * Returns 0 if the constraints are satisfied, a positive
14830 * error code if not and -1 if an internal error occured.
14831 */
14832static int
14833xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14834 xmlSchemaParticlePtr r,
14835 xmlSchemaParticlePtr b)
14836{
14837 xmlSchemaElementPtr elemR, elemB;
14838
14839 /* TODO: Error codes (rcase-NameAndTypeOK). */
14840 elemR = (xmlSchemaElementPtr) r->children;
14841 elemB = (xmlSchemaElementPtr) b->children;
14842 /*
14843 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14844 * the same."
14845 */
14846 if ((elemR != elemB) &&
14847 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14848 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14849 return (1);
14850 /*
14851 * SPEC (2) "R's occurrence range is a valid restriction of B's
14852 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14853 */
14854 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14855 b->minOccurs, b->maxOccurs) != 0)
14856 return (1);
14857 /*
14858 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14859 * {scope} are global."
14860 */
14861 if (elemR == elemB)
14862 return (0);
14863 /*
14864 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14865 */
14866 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14867 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14868 return (1);
14869 /*
14870 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14871 * or is not fixed, or R's declaration's {value constraint} is fixed
14872 * with the same value."
14873 */
14874 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14875 ((elemR->value == NULL) ||
14876 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14877 /* TODO: Equality of the initial value or normalized or canonical? */
14878 (! xmlStrEqual(elemR->value, elemB->value))))
14879 return (1);
14880 /*
14881 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14882 * definitions} is a subset of B's declaration's {identity-constraint
14883 * definitions}, if any."
14884 */
14885 if (elemB->idcs != NULL) {
14886 /* TODO */
14887 }
14888 /*
14889 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14890 * superset of B's declaration's {disallowed substitutions}."
14891 */
14892 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14893 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14894 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14895 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14896 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14897 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14898 return (1);
14899 /*
14900 * SPEC (3.2.5) "R's {type definition} is validly derived given
14901 * {extension, list, union} from B's {type definition}"
14902 *
14903 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14904 * set, if the corresponding constraints handle "restriction" and
14905 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014906 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014907 */
14908 {
14909 int set = 0;
14910
14911 set |= SUBSET_EXTENSION;
14912 set |= SUBSET_LIST;
14913 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014914 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014915 elemB->subtypes, set) != 0)
14916 return (1);
14917 }
14918 return (0);
14919}
14920
14921/**
14922 * xmlSchemaCheckRCaseNSCompat:
14923 * @ctxt: the schema parser context
14924 * @r: the restricting element declaration particle
14925 * @b: the base wildcard particle
14926 *
14927 * (3.9.6) Constraints on Particle Schema Components
14928 * Schema Component Constraint:
14929 * Particle Derivation OK (Elt:Any -- NSCompat)
14930 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014931 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014932 * STATUS: complete
14933 *
14934 * Returns 0 if the constraints are satisfied, a positive
14935 * error code if not and -1 if an internal error occured.
14936 */
14937static int
14938xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14939 xmlSchemaParticlePtr r,
14940 xmlSchemaParticlePtr b)
14941{
14942 /* TODO:Error codes (rcase-NSCompat). */
14943 /*
14944 * SPEC "For an element declaration particle to be a ·valid restriction·
14945 * of a wildcard particle all of the following must be true:"
14946 *
14947 * SPEC (1) "The element declaration's {target namespace} is ·valid·
14948 * with respect to the wildcard's {namespace constraint} as defined by
14949 * Wildcard allows Namespace Name (§3.10.4)."
14950 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014951 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014952 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
14953 return (1);
14954 /*
14955 * SPEC (2) "R's occurrence range is a valid restriction of B's
14956 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14957 */
14958 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14959 b->minOccurs, b->maxOccurs) != 0)
14960 return (1);
14961
14962 return (0);
14963}
14964
14965/**
14966 * xmlSchemaCheckRCaseRecurseAsIfGroup:
14967 * @ctxt: the schema parser context
14968 * @r: the restricting element declaration particle
14969 * @b: the base model group particle
14970 *
14971 * (3.9.6) Constraints on Particle Schema Components
14972 * Schema Component Constraint:
14973 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
14974 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014975 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014976 * STATUS: TODO
14977 *
14978 * Returns 0 if the constraints are satisfied, a positive
14979 * error code if not and -1 if an internal error occured.
14980 */
14981static int
14982xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
14983 xmlSchemaParticlePtr r,
14984 xmlSchemaParticlePtr b)
14985{
14986 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
14987 TODO
14988 return (0);
14989}
14990
14991/**
14992 * xmlSchemaCheckRCaseNSSubset:
14993 * @ctxt: the schema parser context
14994 * @r: the restricting wildcard particle
14995 * @b: the base wildcard particle
14996 *
14997 * (3.9.6) Constraints on Particle Schema Components
14998 * Schema Component Constraint:
14999 * Particle Derivation OK (Any:Any -- NSSubset)
15000 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015001 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015002 * STATUS: complete
15003 *
15004 * Returns 0 if the constraints are satisfied, a positive
15005 * error code if not and -1 if an internal error occured.
15006 */
15007static int
15008xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15009 xmlSchemaParticlePtr r,
15010 xmlSchemaParticlePtr b,
15011 int isAnyTypeBase)
15012{
15013 /* TODO: Error codes (rcase-NSSubset). */
15014 /*
15015 * SPEC (1) "R's occurrence range is a valid restriction of B's
15016 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15017 */
15018 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15019 b->minOccurs, b->maxOccurs))
15020 return (1);
15021 /*
15022 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15023 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15024 */
15025 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15026 (xmlSchemaWildcardPtr) b->children))
15027 return (1);
15028 /*
15029 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15030 * definition·, R's {process contents} must be identical to or stronger
15031 * than B's {process contents}, where strict is stronger than lax is
15032 * stronger than skip."
15033 */
15034 if (! isAnyTypeBase) {
15035 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15036 ((xmlSchemaWildcardPtr) b->children)->processContents)
15037 return (1);
15038 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015039
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015040 return (0);
15041}
15042
15043/**
15044 * xmlSchemaCheckCOSParticleRestrict:
15045 * @ctxt: the schema parser context
15046 * @type: the complex type definition
15047 *
15048 * (3.9.6) Constraints on Particle Schema Components
15049 * Schema Component Constraint:
15050 * Particle Valid (Restriction) (cos-particle-restrict)
15051 *
15052 * STATUS: TODO
15053 *
15054 * Returns 0 if the constraints are satisfied, a positive
15055 * error code if not and -1 if an internal error occured.
15056 */
15057static int
15058xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15059 xmlSchemaParticlePtr r,
15060 xmlSchemaParticlePtr b)
15061{
15062 int ret = 0;
15063
15064 /*part = GET_PARTICLE(type);
15065 basePart = GET_PARTICLE(base);
15066 */
15067
15068 TODO
15069
15070 /*
15071 * SPEC (1) "They are the same particle."
15072 */
15073 if (r == b)
15074 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015075
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015076
15077 return (0);
15078}
15079
15080/**
15081 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15082 * @ctxt: the schema parser context
15083 * @r: the model group particle
15084 * @b: the base wildcard particle
15085 *
15086 * (3.9.6) Constraints on Particle Schema Components
15087 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015088 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015089 * NSRecurseCheckCardinality)
15090 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015091 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015092 * STATUS: TODO: subst-groups
15093 *
15094 * Returns 0 if the constraints are satisfied, a positive
15095 * error code if not and -1 if an internal error occured.
15096 */
15097static int
15098xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15099 xmlSchemaParticlePtr r,
15100 xmlSchemaParticlePtr b)
15101{
15102 xmlSchemaParticlePtr part;
15103 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15104 if ((r->children == NULL) || (r->children->children == NULL))
15105 return (-1);
15106 /*
15107 * SPEC "For a group particle to be a ·valid restriction· of a
15108 * wildcard particle..."
15109 *
15110 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015111 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015112 * Particle Valid (Restriction) (§3.9.6)."
15113 */
15114 part = (xmlSchemaParticlePtr) r->children->children;
15115 do {
15116 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15117 return (1);
15118 part = (xmlSchemaParticlePtr) part->next;
15119 } while (part != NULL);
15120 /*
15121 * SPEC (2) "The effective total range of the group [...] is a
15122 * valid restriction of B's occurrence range as defined by
15123 * Occurrence Range OK (§3.9.6)."
15124 */
15125 if (xmlSchemaCheckParticleRangeOK(
15126 xmlSchemaGetParticleTotalRangeMin(r),
15127 xmlSchemaGetParticleTotalRangeMax(r),
15128 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015129 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015130 return (0);
15131}
15132
15133/**
15134 * xmlSchemaCheckRCaseRecurse:
15135 * @ctxt: the schema parser context
15136 * @r: the <all> or <sequence> model group particle
15137 * @b: the base <all> or <sequence> model group particle
15138 *
15139 * (3.9.6) Constraints on Particle Schema Components
15140 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015141 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015142 Recurse)
15143 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015144 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015145 * STATUS: ?
15146 * TODO: subst-groups
15147 *
15148 * Returns 0 if the constraints are satisfied, a positive
15149 * error code if not and -1 if an internal error occured.
15150 */
15151static int
15152xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15153 xmlSchemaParticlePtr r,
15154 xmlSchemaParticlePtr b)
15155{
15156 /* xmlSchemaParticlePtr part; */
15157 /* TODO: Error codes (rcase-Recurse). */
15158 if ((r->children == NULL) || (b->children == NULL) ||
15159 (r->children->type != b->children->type))
15160 return (-1);
15161 /*
15162 * SPEC "For an all or sequence group particle to be a ·valid
15163 * restriction· of another group particle with the same {compositor}..."
15164 *
15165 * SPEC (1) "R's occurrence range is a valid restriction of B's
15166 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15167 */
15168 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15169 b->minOccurs, b->maxOccurs))
15170 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015171
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015172
15173 return (0);
15174}
15175
15176#endif
15177
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015178#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15179 xmlSchemaPCustomErrExt(pctxt, \
15180 XML_SCHEMAP_INVALID_FACET_VALUE, \
15181 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15182 "It is an error for both '%s' and '%s' to be specified on the "\
15183 "same type definition", \
15184 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15185 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15186
15187#define FACET_RESTR_ERR(fac1, msg) \
15188 xmlSchemaPCustomErr(pctxt, \
15189 XML_SCHEMAP_INVALID_FACET_VALUE, \
15190 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015191 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015192
15193#define FACET_RESTR_FIXED_ERR(fac) \
15194 xmlSchemaPCustomErr(pctxt, \
15195 XML_SCHEMAP_INVALID_FACET_VALUE, \
15196 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15197 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015198 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015199
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015200static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015201xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15202 xmlSchemaFacetPtr facet1,
15203 xmlSchemaFacetPtr facet2,
15204 int lessGreater,
15205 int orEqual,
15206 int ofBase)
15207{
15208 xmlChar *msg = NULL;
15209
15210 msg = xmlStrdup(BAD_CAST "'");
15211 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15212 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15213 if (lessGreater == 0)
15214 msg = xmlStrcat(msg, BAD_CAST " equal to");
15215 if (lessGreater == 1)
15216 msg = xmlStrcat(msg, BAD_CAST " greater than");
15217 else
15218 msg = xmlStrcat(msg, BAD_CAST " less than");
15219
15220 if (orEqual)
15221 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15222 msg = xmlStrcat(msg, BAD_CAST " '");
15223 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15224 if (ofBase)
15225 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15226 else
15227 msg = xmlStrcat(msg, BAD_CAST "'");
15228
15229 xmlSchemaPCustomErr(pctxt,
15230 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015231 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015232 (const char *) msg, NULL);
15233
15234 if (msg != NULL)
15235 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015236}
15237
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015238static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015239xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15240 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015241{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015242 xmlSchemaTypePtr base = type->baseType;
15243 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015244 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015245 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15246 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15247 fmininc = NULL, fmaxinc = NULL,
15248 fminexc = NULL, fmaxexc = NULL,
15249 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15250 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15251 bfmininc = NULL, bfmaxinc = NULL,
15252 bfminexc = NULL, bfmaxexc = NULL;
15253 int res, err = 0, fixedErr;
15254 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015255 * 3 The {facets} of R are the union of S and the {facets}
15256 * of B, eliminating duplicates. To eliminate duplicates,
15257 * when a facet of the same kind occurs in both S and the
15258 * {facets} of B, the one in the {facets} of B is not
15259 * included, with the exception of enumeration and pattern
15260 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015261 * are allowed.
15262 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015263
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015264 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15265 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015266
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015267 last = type->facetSet;
15268 if (last != NULL)
15269 while (last->next != NULL)
15270 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015271
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015272 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15273 facet = cur->facet;
15274 switch (facet->type) {
15275 case XML_SCHEMA_FACET_LENGTH:
15276 flength = facet; break;
15277 case XML_SCHEMA_FACET_MINLENGTH:
15278 fminlen = facet; break;
15279 case XML_SCHEMA_FACET_MININCLUSIVE:
15280 fmininc = facet; break;
15281 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15282 fminexc = facet; break;
15283 case XML_SCHEMA_FACET_MAXLENGTH:
15284 fmaxlen = facet; break;
15285 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15286 fmaxinc = facet; break;
15287 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15288 fmaxexc = facet; break;
15289 case XML_SCHEMA_FACET_TOTALDIGITS:
15290 ftotdig = facet; break;
15291 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15292 ffracdig = facet; break;
15293 default:
15294 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015295 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015296 }
15297 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15298 facet = cur->facet;
15299 switch (facet->type) {
15300 case XML_SCHEMA_FACET_LENGTH:
15301 bflength = facet; break;
15302 case XML_SCHEMA_FACET_MINLENGTH:
15303 bfminlen = facet; break;
15304 case XML_SCHEMA_FACET_MININCLUSIVE:
15305 bfmininc = facet; break;
15306 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15307 bfminexc = facet; break;
15308 case XML_SCHEMA_FACET_MAXLENGTH:
15309 bfmaxlen = facet; break;
15310 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15311 bfmaxinc = facet; break;
15312 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15313 bfmaxexc = facet; break;
15314 case XML_SCHEMA_FACET_TOTALDIGITS:
15315 bftotdig = facet; break;
15316 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15317 bffracdig = facet; break;
15318 default:
15319 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015320 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015321 }
15322 err = 0;
15323 /*
15324 * length and minLength or maxLength (2.2) + (3.2)
15325 */
15326 if (flength && (fminlen || fmaxlen)) {
15327 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15328 "either of 'minLength' or 'maxLength' to be specified on "
15329 "the same type definition")
15330 }
15331 /*
15332 * Mutual exclusions in the same derivation step.
15333 */
15334 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015335 /*
15336 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015337 */
15338 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15339 }
15340 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015341 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015342 * SCC "minInclusive and minExclusive"
15343 */
15344 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015345 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015346
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015347 if (flength && bflength) {
15348 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015349 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015350 * The values have to be equal.
15351 */
15352 res = xmlSchemaCompareValues(flength->val, bflength->val);
15353 if (res == -2)
15354 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015355 if (res != 0)
15356 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15357 if ((res != 0) && (bflength->fixed)) {
15358 FACET_RESTR_FIXED_ERR(flength)
15359 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015360
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015361 }
15362 if (fminlen && bfminlen) {
15363 /*
15364 * SCC "minLength valid restriction"
15365 * minLength >= BASE minLength
15366 */
15367 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15368 if (res == -2)
15369 goto internal_error;
15370 if (res == -1)
15371 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15372 if ((res != 0) && (bfminlen->fixed)) {
15373 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015374 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015375 }
15376 if (fmaxlen && bfmaxlen) {
15377 /*
15378 * SCC "maxLength valid restriction"
15379 * maxLength <= BASE minLength
15380 */
15381 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15382 if (res == -2)
15383 goto internal_error;
15384 if (res == 1)
15385 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15386 if ((res != 0) && (bfmaxlen->fixed)) {
15387 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015388 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015389 }
15390 /*
15391 * SCC "length and minLength or maxLength"
15392 */
15393 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015394 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015395 if (flength) {
15396 if (! fminlen)
15397 flength = bflength;
15398 if (fminlen) {
15399 /* (1.1) length >= minLength */
15400 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15401 if (res == -2)
15402 goto internal_error;
15403 if (res == -1)
15404 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15405 }
15406 if (! fmaxlen)
15407 fmaxlen = bfmaxlen;
15408 if (fmaxlen) {
15409 /* (2.1) length <= maxLength */
15410 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15411 if (res == -2)
15412 goto internal_error;
15413 if (res == 1)
15414 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15415 }
15416 }
15417 if (fmaxinc) {
15418 /*
15419 * "maxInclusive"
15420 */
15421 if (fmininc) {
15422 /* SCC "maxInclusive >= minInclusive" */
15423 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15424 if (res == -2)
15425 goto internal_error;
15426 if (res == -1) {
15427 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15428 }
15429 }
15430 /*
15431 * SCC "maxInclusive valid restriction"
15432 */
15433 if (bfmaxinc) {
15434 /* maxInclusive <= BASE maxInclusive */
15435 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15436 if (res == -2)
15437 goto internal_error;
15438 if (res == 1)
15439 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15440 if ((res != 0) && (bfmaxinc->fixed)) {
15441 FACET_RESTR_FIXED_ERR(fmaxinc)
15442 }
15443 }
15444 if (bfmaxexc) {
15445 /* maxInclusive < BASE maxExclusive */
15446 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15447 if (res == -2)
15448 goto internal_error;
15449 if (res != -1) {
15450 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15451 }
15452 }
15453 if (bfmininc) {
15454 /* maxInclusive >= BASE minInclusive */
15455 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15456 if (res == -2)
15457 goto internal_error;
15458 if (res == -1) {
15459 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15460 }
15461 }
15462 if (bfminexc) {
15463 /* maxInclusive > BASE minExclusive */
15464 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15465 if (res == -2)
15466 goto internal_error;
15467 if (res != 1) {
15468 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15469 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015470 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015471 }
15472 if (fmaxexc) {
15473 /*
15474 * "maxExclusive >= minExclusive"
15475 */
15476 if (fminexc) {
15477 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15478 if (res == -2)
15479 goto internal_error;
15480 if (res == -1) {
15481 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15482 }
15483 }
15484 /*
15485 * "maxExclusive valid restriction"
15486 */
15487 if (bfmaxexc) {
15488 /* maxExclusive <= BASE maxExclusive */
15489 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15490 if (res == -2)
15491 goto internal_error;
15492 if (res == 1) {
15493 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15494 }
15495 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015496 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015497 }
15498 }
15499 if (bfmaxinc) {
15500 /* maxExclusive <= BASE maxInclusive */
15501 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15502 if (res == -2)
15503 goto internal_error;
15504 if (res == 1) {
15505 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15506 }
15507 }
15508 if (bfmininc) {
15509 /* maxExclusive > BASE minInclusive */
15510 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15511 if (res == -2)
15512 goto internal_error;
15513 if (res != 1) {
15514 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15515 }
15516 }
15517 if (bfminexc) {
15518 /* maxExclusive > BASE minExclusive */
15519 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15520 if (res == -2)
15521 goto internal_error;
15522 if (res != 1) {
15523 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15524 }
15525 }
15526 }
15527 if (fminexc) {
15528 /*
15529 * "minExclusive < maxInclusive"
15530 */
15531 if (fmaxinc) {
15532 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15533 if (res == -2)
15534 goto internal_error;
15535 if (res != -1) {
15536 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15537 }
15538 }
15539 /*
15540 * "minExclusive valid restriction"
15541 */
15542 if (bfminexc) {
15543 /* minExclusive >= BASE minExclusive */
15544 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15545 if (res == -2)
15546 goto internal_error;
15547 if (res == -1) {
15548 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15549 }
15550 if ((res != 0) && (bfminexc->fixed)) {
15551 FACET_RESTR_FIXED_ERR(fminexc)
15552 }
15553 }
15554 if (bfmaxinc) {
15555 /* minExclusive <= BASE maxInclusive */
15556 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15557 if (res == -2)
15558 goto internal_error;
15559 if (res == 1) {
15560 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15561 }
15562 }
15563 if (bfmininc) {
15564 /* minExclusive >= BASE minInclusive */
15565 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15566 if (res == -2)
15567 goto internal_error;
15568 if (res == -1) {
15569 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15570 }
15571 }
15572 if (bfmaxexc) {
15573 /* minExclusive < BASE maxExclusive */
15574 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15575 if (res == -2)
15576 goto internal_error;
15577 if (res != -1) {
15578 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15579 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015580 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015581 }
15582 if (fmininc) {
15583 /*
15584 * "minInclusive < maxExclusive"
15585 */
15586 if (fmaxexc) {
15587 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15588 if (res == -2)
15589 goto internal_error;
15590 if (res != -1) {
15591 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15592 }
15593 }
15594 /*
15595 * "minExclusive valid restriction"
15596 */
15597 if (bfmininc) {
15598 /* minInclusive >= BASE minInclusive */
15599 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15600 if (res == -2)
15601 goto internal_error;
15602 if (res == -1) {
15603 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15604 }
15605 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015606 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015607 }
15608 }
15609 if (bfmaxinc) {
15610 /* minInclusive <= BASE maxInclusive */
15611 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15612 if (res == -2)
15613 goto internal_error;
15614 if (res == -1) {
15615 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15616 }
15617 }
15618 if (bfminexc) {
15619 /* minInclusive > BASE minExclusive */
15620 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15621 if (res == -2)
15622 goto internal_error;
15623 if (res != 1)
15624 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15625 }
15626 if (bfmaxexc) {
15627 /* minInclusive < BASE maxExclusive */
15628 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15629 if (res == -2)
15630 goto internal_error;
15631 if (res != -1)
15632 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15633 }
15634 }
15635 if (ftotdig && bftotdig) {
15636 /*
15637 * SCC " totalDigits valid restriction"
15638 * totalDigits <= BASE totalDigits
15639 */
15640 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15641 if (res == -2)
15642 goto internal_error;
15643 if (res == 1)
15644 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15645 -1, 1, 1);
15646 if ((res != 0) && (bftotdig->fixed)) {
15647 FACET_RESTR_FIXED_ERR(ftotdig)
15648 }
15649 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015650 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015651 /*
15652 * SCC "fractionDigits valid restriction"
15653 * fractionDigits <= BASE fractionDigits
15654 */
15655 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15656 if (res == -2)
15657 goto internal_error;
15658 if (res == 1)
15659 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15660 -1, 1, 1);
15661 if ((res != 0) && (bffracdig->fixed)) {
15662 FACET_RESTR_FIXED_ERR(ffracdig)
15663 }
15664 }
15665 /*
15666 * SCC "fractionDigits less than or equal to totalDigits"
15667 */
15668 if (! ftotdig)
15669 ftotdig = bftotdig;
15670 if (! ffracdig)
15671 ffracdig = bffracdig;
15672 if (ftotdig && ffracdig) {
15673 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15674 if (res == -2)
15675 goto internal_error;
15676 if (res == 1)
15677 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15678 -1, 1, 0);
15679 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015680 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015681 * *Enumerations* won' be added here, since only the first set
15682 * of enumerations in the ancestor-or-self axis is used
15683 * for validation, plus we need to use the base type of those
15684 * enumerations for whitespace.
15685 *
15686 * *Patterns*: won't be add here, since they are ORed at
15687 * type level and ANDed at ancestor level. This will
15688 * happed during validation by walking the base axis
15689 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015690 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015691 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15692 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015693 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015694 * Special handling of enumerations and patterns.
15695 * TODO: hmm, they should not appear in the set, so remove this.
15696 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015697 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015698 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015699 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015700 /*
15701 * Search for a duplicate facet in the current type.
15702 */
15703 link = type->facetSet;
15704 err = 0;
15705 fixedErr = 0;
15706 while (link != NULL) {
15707 facet = link->facet;
15708 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015709 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015710 case XML_SCHEMA_FACET_WHITESPACE:
15711 /*
15712 * The whitespace must be stronger.
15713 */
15714 if (facet->whitespace < bfacet->whitespace) {
15715 FACET_RESTR_ERR(flength,
15716 "The 'whitespace' value has to be equal to "
15717 "or stronger than the 'whitespace' value of "
15718 "the base type")
15719 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015720 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015721 (facet->whitespace != bfacet->whitespace)) {
15722 FACET_RESTR_FIXED_ERR(facet)
15723 }
15724 break;
15725 default:
15726 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015727 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015728 /* Duplicate found. */
15729 break;
15730 }
15731 link = link->next;
15732 }
15733 /*
15734 * If no duplicate was found: add the base types's facet
15735 * to the set.
15736 */
15737 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015738 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015739 xmlMalloc(sizeof(xmlSchemaFacetLink));
15740 if (link == NULL) {
15741 xmlSchemaPErrMemory(pctxt,
15742 "deriving facets, creating a facet link", NULL);
15743 return (-1);
15744 }
15745 link->facet = cur->facet;
15746 link->next = NULL;
15747 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015748 type->facetSet = link;
15749 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015750 last->next = link;
15751 last = link;
15752 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015753
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015754 }
15755
15756 return (0);
15757internal_error:
15758 xmlSchemaPCustomErr(pctxt,
15759 XML_SCHEMAP_INVALID_FACET_VALUE,
15760 NULL, type, NULL,
15761 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15762 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015763}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015764
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015765static int
15766xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15767 xmlSchemaTypePtr type)
15768{
15769 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15770 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015771 * The actual value is then formed by replacing any union type
15772 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015773 * {member type definitions}, in order.
15774 */
15775 link = type->memberTypes;
15776 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015777
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015778 if (IS_NOT_TYPEFIXED(link->type))
15779 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15780
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015781 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015782 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015783 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015784 link->type = subLink->type;
15785 if (subLink->next != NULL) {
15786 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015787 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015788 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015789 while (subLink != NULL) {
15790 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015791 xmlMalloc(sizeof(xmlSchemaTypeLink));
15792 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015793 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015794 NULL);
15795 return (-1);
15796 }
15797 newLink->type = subLink->type;
15798 prevLink->next = newLink;
15799 prevLink = newLink;
15800 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015801
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015802 subLink = subLink->next;
15803 }
15804 }
15805 }
15806 }
15807 link = link->next;
15808 }
15809 return (0);
15810}
15811
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015812static void
15813xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15814{
15815 int has = 0, needVal = 0, normVal = 0;
15816
15817 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15818 if (has) {
15819 needVal = (type->baseType->flags &
15820 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15821 normVal = (type->baseType->flags &
15822 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15823 }
15824 if (type->facets != NULL) {
15825 xmlSchemaFacetPtr fac;
15826
15827 for (fac = type->facets; fac != NULL; fac = fac->next) {
15828 switch (fac->type) {
15829 case XML_SCHEMA_FACET_WHITESPACE:
15830 break;
15831 case XML_SCHEMA_FACET_PATTERN:
15832 normVal = 1;
15833 has = 1;
15834 break;
15835 case XML_SCHEMA_FACET_ENUMERATION:
15836 needVal = 1;
15837 normVal = 1;
15838 has = 1;
15839 break;
15840 default:
15841 has = 1;
15842 break;
15843 }
15844 }
15845 }
15846 if (normVal)
15847 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15848 if (needVal)
15849 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15850 if (has)
15851 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15852
15853 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15854 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15855 /*
15856 * OPTIMIZE VAL TODO: Some facets need a computed value.
15857 */
15858 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15859 (prim->builtInType != XML_SCHEMAS_STRING)) {
15860 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15861 }
15862 }
15863}
15864
15865static int
15866xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15867{
15868
15869
15870 /*
15871 * Evaluate the whitespace-facet value.
15872 */
15873 if (VARIETY_LIST(type)) {
15874 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15875 return (0);
15876 } else if (VARIETY_UNION(type))
15877 return (0);
15878
15879 if (type->facetSet != NULL) {
15880 xmlSchemaFacetLinkPtr lin;
15881
15882 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15883 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15884 switch (lin->facet->whitespace) {
15885 case XML_SCHEMAS_FACET_PRESERVE:
15886 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15887 break;
15888 case XML_SCHEMAS_FACET_REPLACE:
15889 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15890 break;
15891 case XML_SCHEMAS_FACET_COLLAPSE:
15892 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15893 break;
15894 default:
15895 return (-1);
15896 }
15897 return (0);
15898 }
15899 }
15900 }
15901 /*
15902 * For all ·atomic· datatypes other than string (and types ·derived·
15903 * by ·restriction· from it) the value of whiteSpace is fixed to
15904 * collapse
15905 */
15906 {
15907 xmlSchemaTypePtr anc;
15908
15909 for (anc = type->baseType; anc != NULL &&
15910 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15911 anc = anc->baseType) {
15912
15913 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15914 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15915 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15916
15917 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15918 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15919 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15920
15921 } else
15922 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15923 break;
15924 }
15925 }
15926 return (0);
15927 }
15928 return (0);
15929}
15930
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015931/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015932 * xmlSchemaTypeFixup:
15933 * @typeDecl: the schema type definition
15934 * @ctxt: the schema parser context
15935 *
15936 * Fixes the content model of the type.
15937 */
15938static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015939xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015940 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015941{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015942 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015943 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015944 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15945 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015946 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015947 if (! IS_NOT_TYPEFIXED(type))
15948 return;
15949 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000015950 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015951 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015952
15953 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015954 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015955 XML_SCHEMAP_INTERNAL,
15956 NULL, type, NULL,
15957 "Internal error: xmlSchemaTypeFixup, "
15958 "baseType is missing on '%s'", type->name);
15959 return;
15960 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015961
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015962 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015963 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015964
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015965 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015966 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015967 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015968 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015969 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015970 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
15971 /*
15972 * Skip fixup if the base type is invalid.
15973 * TODO: Generate a warning!
15974 */
15975 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015976 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015977 /*
15978 * This basically checks if the base type can be derived.
15979 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015980 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015981 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
15982 return;
15983 }
15984 /*
15985 * Fixup the content type.
15986 */
15987 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
15988 /*
15989 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015990 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015991 if ((IS_COMPLEX_TYPE(baseType)) &&
15992 (baseType->contentTypeDef != NULL) &&
15993 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015994 xmlSchemaTypePtr contentBase, content;
15995 char buf[30];
15996 const xmlChar *tmpname;
15997 /*
15998 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015999 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016000 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016001 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016002 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016003 * SPEC (1.1) "the simple type definition corresponding to the
16004 * <simpleType> among the [children] of <restriction> if there
16005 * is one;"
16006 * Note that this "<simpleType> among the [children]" was put
16007 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016008 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016009 contentBase = type->contentTypeDef;
16010 type->contentTypeDef = NULL;
16011 } else {
16012 /*
16013 * (1.2) "...otherwise (<restriction> has no <simpleType>
16014 * among its [children]), the simple type definition which
16015 * is the {content type} of the ... base type."
16016 */
16017 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016018 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016019 /*
16020 * SPEC
16021 * "... a simple type definition which restricts the simple
16022 * type definition identified in clause 1.1 or clause 1.2
16023 * with a set of facet components"
16024 *
16025 * Create the anonymous simple type, which will be the content
16026 * type of the complex type.
16027 */
16028 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16029 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16030 content = xmlSchemaAddType(pctxt,
16031 pctxt->schema, tmpname, tmpname, type->node);
16032 if (content == NULL)
16033 return;
16034 /*
16035 * We will use the same node as for the <complexType>
16036 * to have it somehow anchored in the schema doc.
16037 */
16038 content->node = type->node;
16039 content->type = XML_SCHEMA_TYPE_SIMPLE;
16040 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16041 content->baseType = contentBase;
16042 /*
16043 * Move the facets, previously anchored on the complexType.
16044 */
16045 content->facets = type->facets;
16046 type->facets = NULL;
16047 content->facetSet = type->facetSet;
16048 type->facetSet = NULL;
16049
16050 type->contentTypeDef = content;
16051 if (IS_NOT_TYPEFIXED(contentBase))
16052 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16053 xmlSchemaTypeFixup(content, pctxt, NULL);
16054
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016055 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16056 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16057 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16058 /*
16059 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16060 * an emptiable particle, then a simple type definition which
16061 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016062 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016063 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016064 (type->contentTypeDef->baseType == NULL)) {
16065 /*
16066 * TODO: Check if this ever happens.
16067 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016068 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016069 XML_SCHEMAP_INTERNAL,
16070 NULL, type, NULL,
16071 "Internal error: xmlSchemaTypeFixup, "
16072 "complex type '%s': the <simpleContent><restriction> "
16073 "is missing a <simpleType> child, but was not catched "
16074 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016075 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016076 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16077 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16078 /*
16079 * SPEC (3) If <extension> + base is <complexType> with
16080 * <simpleType> content, "...then the {content type} of that
16081 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016082 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016083 if (baseType->contentTypeDef == NULL) {
16084 /*
16085 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16086 * should have catched this already.
16087 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016088 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016089 XML_SCHEMAP_INTERNAL,
16090 NULL, type, NULL,
16091 "Internal error: xmlSchemaTypeFixup, "
16092 "complex type '%s': the <extension>ed base type is "
16093 "a complex type with no simple content type",
16094 type->name);
16095 }
16096 type->contentTypeDef = baseType->contentTypeDef;
16097 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16098 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16099 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016100 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016101 * "... then that simple type definition"
16102 */
16103 type->contentTypeDef = baseType;
16104 } else {
16105 /*
16106 * TODO: Check if this ever happens.
16107 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016108 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016109 XML_SCHEMAP_INTERNAL,
16110 NULL, type, NULL,
16111 "Internal error: xmlSchemaTypeFixup, "
16112 "complex type '%s' with <simpleContent>: unhandled "
16113 "derivation case", type->name);
16114 }
16115 } else {
16116 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016117 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016118 (xmlSchemaParticlePtr) type->subtypes;
16119 /*
16120 * Corresponds to <complexType><complexContent>...
16121 *
16122 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016123 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016124 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016125 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016126 * Compute the "effective content":
16127 * (2.1.1) + (2.1.2) + (2.1.3)
16128 */
16129 if ((particle == NULL) ||
16130 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16131 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16132 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16133 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16134 (particle->minOccurs == 0))) &&
16135 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016136 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016137 /*
16138 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16139 * a particle whose properties are as follows:..."
16140 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016141 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016142 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16143 * NOTE that we sill assign it the <complexType> node to
16144 * somehow anchor it in the doc.
16145 */
16146 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016147 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016148 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016149 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016150 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016151 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016152 type->node, 1, 1);
16153 if (particle == NULL)
16154 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016155 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016156 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016157 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016158 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016159 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016160 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16161 if (particle->children == NULL)
16162 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016163
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016164 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016165 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016166 dummySequence = 1;
16167 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16168 } else {
16169 /*
16170 * SPEC (2.1.5) "otherwise empty"
16171 */
16172 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016173 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016174 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016175 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016176 * SPEC (2.2) "otherwise the particle corresponding to the
16177 * <all>, <choice>, <group> or <sequence> among the
16178 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016179 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016180 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16181 }
16182 /*
16183 * Compute the "content type".
16184 */
16185 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016186 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016187 * SPEC (3.1) "If <restriction>..."
16188 * (3.1.1) + (3.1.2) */
16189 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16190 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16191 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16192 }
16193 } else {
16194 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016195 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016196 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016197 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16198 /*
16199 * SPEC (3.2.1)
16200 */
16201 type->contentType = baseType->contentType;
16202 type->subtypes = baseType->subtypes;
16203 /*
16204 * NOTE that the effective mixed is ignored here.
16205 */
16206 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16207 /*
16208 * SPEC (3.2.2)
16209 */
16210 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16211 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16212 } else {
16213 /*
16214 * SPEC (3.2.3)
16215 */
16216 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16217 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16218 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016219 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016220 * {particles} are..."
16221 */
16222 if (! dummySequence) {
16223 xmlSchemaTreeItemPtr effectiveContent =
16224 (xmlSchemaTreeItemPtr) type->subtypes;
16225 /*
16226 * Create the particle.
16227 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016228 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016229 type->node, 1, 1);
16230 if (particle == NULL)
16231 return;
16232 /*
16233 * Create the "sequence" model group.
16234 */
16235 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016236 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016237 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16238 if (particle->children == NULL)
16239 return;
16240 type->subtypes = (xmlSchemaTypePtr) particle;
16241 /*
16242 * SPEC "the particle of the {content type} of
16243 * the ... base ..."
16244 * Create a duplicate of the base type's particle
16245 * and assign its "term" to it.
16246 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016247 particle->children->children =
16248 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16249 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016250 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016251 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016252 if (particle->children->children == NULL)
16253 return;
16254 particle = (xmlSchemaParticlePtr)
16255 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016256 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016257 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16258 /*
16259 * SPEC "followed by the ·effective content·."
16260 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016261 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016262 } else {
16263 /*
16264 * This is the case when there is already an empty
16265 * <sequence> with minOccurs==maxOccurs==1.
16266 * Just add the base types's content type.
16267 * NOTE that, although we miss to add an intermediate
16268 * <sequence>, this should produce no difference to
16269 * neither the regex compilation of the content model,
16270 * nor to the complex type contraints.
16271 */
16272 particle->children->children =
16273 (xmlSchemaTreeItemPtr) baseType->subtypes;
16274 }
16275 }
16276 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016277 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016278 /*
16279 * Apply the complex type component constraints; this will not
16280 * check attributes, since this is done in
16281 * xmlSchemaBuildAttributeValidation().
16282 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016283 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16284 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016285 /*
16286 * Inherit & check constraints for attributes.
16287 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016288 xmlSchemaBuildAttributeValidation(pctxt, type);
16289 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016290 /*
16291 * Simple Type Definition Schema Component
16292 */
16293 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016294 if (VARIETY_LIST(type)) {
16295 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016296 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016297 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016298 if (type->subtypes == NULL) {
16299 /*
16300 * This one is really needed, so get out.
16301 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016302 PERROR_INT("xmlSchemaTypeFixup",
16303 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016304 return;
16305 }
16306 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016307 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16308 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016309 /*
16310 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016311 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016312 if (type->memberTypes == NULL) {
16313 /*
16314 * This one is really needed, so get out.
16315 */
16316 return;
16317 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016318 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016319 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016320 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016321 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016322 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016323 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016324 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016325 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016326 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16327 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016328 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016329 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016330 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016331 */
16332 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016333 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016334 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016335 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16336 /*
16337 * Inherit the itemType.
16338 */
16339 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016340 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016341 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16342 /*
16343 * NOTE that we won't assign the memberTypes of the base,
16344 * since this will make trouble when freeing them; we will
16345 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016346 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016347 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016348 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016349 /*
16350 * Check constraints.
16351 *
16352 * TODO: Split this somehow, we need to know first if we can derive
16353 * from the base type at all!
16354 */
16355 if (type->baseType != NULL) {
16356 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016357 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016358 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016359 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016360 * applied beforehand.
16361 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016362 xmlSchemaCheckSRCSimpleType(pctxt, type);
16363 xmlSchemaCheckFacetValues(type, pctxt);
16364 if ((type->facetSet != NULL) ||
16365 (type->baseType->facetSet != NULL))
16366 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16367 /*
16368 * Whitespace value.
16369 */
16370 xmlSchemaTypeFixupWhitespace(type);
16371 xmlSchemaTypeFixupOptimFacets(type);
16372 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016373 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016374
Daniel Veillard8651f532002-04-17 09:06:27 +000016375#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016377 xmlGenericError(xmlGenericErrorContext,
16378 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016379 type->node->doc->URL,
16380 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016381 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016382 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016383 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016384 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16385 switch (type->contentType) {
16386 case XML_SCHEMA_CONTENT_SIMPLE:
16387 xmlGenericError(xmlGenericErrorContext, "simple\n");
16388 break;
16389 case XML_SCHEMA_CONTENT_ELEMENTS:
16390 xmlGenericError(xmlGenericErrorContext, "elements\n");
16391 break;
16392 case XML_SCHEMA_CONTENT_UNKNOWN:
16393 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16394 break;
16395 case XML_SCHEMA_CONTENT_EMPTY:
16396 xmlGenericError(xmlGenericErrorContext, "empty\n");
16397 break;
16398 case XML_SCHEMA_CONTENT_MIXED:
16399 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016400 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016401 xmlGenericError(xmlGenericErrorContext,
16402 "mixed as emptiable particle\n");
16403 else
16404 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16405 break;
16406 /* Removed, since not used. */
16407 /*
16408 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16409 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16410 break;
16411 */
16412 case XML_SCHEMA_CONTENT_BASIC:
16413 xmlGenericError(xmlGenericErrorContext, "basic\n");
16414 break;
16415 default:
16416 xmlGenericError(xmlGenericErrorContext,
16417 "not registered !!!\n");
16418 break;
16419 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016420 }
16421#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016422}
16423
16424/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016425 * xmlSchemaCheckFacet:
16426 * @facet: the facet
16427 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016428 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016429 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016430 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016431 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016432 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016433 * Returns 0 if valid, a positive error code if not valid and
16434 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016435 */
16436int
16437xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016438 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016439 xmlSchemaParserCtxtPtr pctxt,
16440 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016441{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016442 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016443
Daniel Veillardce682bc2004-11-05 17:22:25 +000016444 if ((facet == NULL) || (typeDecl == NULL))
16445 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016446 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016447 * TODO: will the parser context be given if used from
16448 * the relaxNG module?
16449 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016450 if (pctxt == NULL)
16451 ctxtGiven = 0;
16452 else
16453 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016454
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016455 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016456 case XML_SCHEMA_FACET_MININCLUSIVE:
16457 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16458 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016459 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16460 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016461 /*
16462 * Okay we need to validate the value
16463 * at that point.
16464 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016465 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016466
16467 /* 4.3.5.5 Constraints on enumeration Schema Components
16468 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016469 * It is an ·error· if any member of {value} is not in the
16470 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016471 *
16472 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016473 * The value ·must· be in the
16474 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016475 */
16476 /*
16477 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016478 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016479 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016480 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016481 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016482 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016483 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016484 */
16485 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16486 base = typeDecl->baseType;
16487 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016488 PERROR_INT("xmlSchemaCheckFacet",
16489 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016490 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016491 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016492 } else
16493 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016494
16495 if (! ctxtGiven) {
16496 /*
16497 * A context is needed if called from RelaxNG.
16498 */
16499 pctxt = xmlSchemaNewParserCtxt("*");
16500 if (pctxt == NULL)
16501 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016502 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016503 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016504 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016505 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016506 * facet->node is just the node holding the facet
16507 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016508 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016509 */
16510 ret = xmlSchemaVCheckCVCSimpleType(
16511 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16512 facet->value, &(facet->val), 1, 1, 0);
16513 if (ret != 0) {
16514 if (ret < 0) {
16515 /* No error message for RelaxNG. */
16516 if (ctxtGiven) {
16517 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16518 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16519 "Internal error: xmlSchemaCheckFacet, "
16520 "failed to validate the value '%s' of the "
16521 "facet '%s' against the base type",
16522 facet->value, xmlSchemaFacetTypeToString(facet->type));
16523 }
16524 goto internal_error;
16525 }
16526 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16527 /* No error message for RelaxNG. */
16528 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016529 xmlChar *str = NULL;
16530
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016531 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16532 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016533 "The value '%s' of the facet does not validate "
16534 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016535 facet->value,
16536 xmlSchemaFormatQName(&str,
16537 base->targetNamespace, base->name));
16538 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016539 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016540 goto exit;
16541 } else if (facet->val == NULL) {
16542 if (ctxtGiven) {
16543 PERROR_INT("xmlSchemaCheckFacet",
16544 "value was not computed");
16545 }
16546 TODO
16547 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016548 break;
16549 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016550 case XML_SCHEMA_FACET_PATTERN:
16551 facet->regexp = xmlRegexpCompile(facet->value);
16552 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016553 ret = XML_SCHEMAP_REGEXP_INVALID;
16554 /* No error message for RelaxNG. */
16555 if (ctxtGiven) {
16556 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16557 ret, facet->node, typeDecl,
16558 "The value '%s' of the facet 'pattern' is not a "
16559 "valid regular expression",
16560 facet->value, NULL);
16561 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016562 }
16563 break;
16564 case XML_SCHEMA_FACET_TOTALDIGITS:
16565 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16566 case XML_SCHEMA_FACET_LENGTH:
16567 case XML_SCHEMA_FACET_MAXLENGTH:
16568 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016569 ret = xmlSchemaValidatePredefinedType(
16570 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16571 facet->value, &(facet->val));
16572 if (ret != 0) {
16573 if (ret < 0) {
16574 /* No error message for RelaxNG. */
16575 if (ctxtGiven) {
16576 PERROR_INT("xmlSchemaCheckFacet",
16577 "validating facet value");
16578 }
16579 goto internal_error;
16580 }
16581 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16582 /* No error message for RelaxNG. */
16583 if (ctxtGiven) {
16584 /* error code */
16585 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16586 ret, facet->node, typeDecl,
16587 "The value '%s' of the facet '%s' is not a valid "
16588 "'nonNegativeInteger'",
16589 facet->value,
16590 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016591 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016592 }
16593 break;
16594 }
16595 case XML_SCHEMA_FACET_WHITESPACE:{
16596 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16597 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16598 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16599 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16600 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16601 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16602 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016603 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16604 /* No error message for RelaxNG. */
16605 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016606 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016607 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16608 ret, facet->node, typeDecl,
16609 "The value '%s' of the facet 'whitespace' is not "
16610 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016611 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016612 }
16613 }
16614 default:
16615 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016616 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016617exit:
16618 if ((! ctxtGiven) && (pctxt != NULL))
16619 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016620 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016621internal_error:
16622 if ((! ctxtGiven) && (pctxt != NULL))
16623 xmlSchemaFreeParserCtxt(pctxt);
16624 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016625}
16626
16627/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016628 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016629 * @typeDecl: the schema type definition
16630 * @ctxt: the schema parser context
16631 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016632 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016633 */
16634static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016635xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16636 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016637{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016638 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016639 /*
16640 * NOTE: It is intended to use the facets list, instead
16641 * of facetSet.
16642 */
16643 if (typeDecl->facets != NULL) {
16644 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016645
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016646 /*
16647 * Temporarily assign the "schema" to the validation context
16648 * of the parser context. This is needed for NOTATION validation.
16649 */
16650 if (ctxt->vctxt == NULL) {
16651 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16652 return;
16653 }
16654 ctxt->vctxt->schema = ctxt->schema;
16655
Daniel Veillard01fa6152004-06-29 17:04:39 +000016656 while (facet != NULL) {
16657 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16658 facet = facet->next;
16659 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016660
16661 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016662 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016663}
16664
16665/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016666 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016667 * @ctxtMGroup: the searched model group
16668 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016669 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016670 *
16671 * This one is intended to be used by
16672 * xmlSchemaCheckGroupDefCircular only.
16673 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016674 * Returns the particle with the circular model group definition reference,
16675 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016676 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016677static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016678xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016679 xmlSchemaTreeItemPtr particle)
16680{
16681 xmlSchemaTreeItemPtr circ = NULL;
16682 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016683 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016684
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016685 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016686 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016687 if (term == NULL)
16688 continue;
16689 switch (term->type) {
16690 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016691 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016692 if (gdef == groupDef)
16693 return (particle);
16694 /*
16695 * Mark this model group definition to avoid infinite
16696 * recursion on circular references not yet examined.
16697 */
16698 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16699 continue;
16700 if (gdef->children != NULL) {
16701 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16702 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16703 gdef->children->children);
16704 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16705 if (circ != NULL)
16706 return (circ);
16707 }
16708 break;
16709 case XML_SCHEMA_TYPE_SEQUENCE:
16710 case XML_SCHEMA_TYPE_CHOICE:
16711 case XML_SCHEMA_TYPE_ALL:
16712 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16713 if (circ != NULL)
16714 return (circ);
16715 break;
16716 default:
16717 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016718 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016719 }
16720 return (NULL);
16721}
16722
16723/**
16724 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016725 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016726 * @ctxt: the parser context
16727 * @name: the name
16728 *
16729 * Checks for circular references to model group definitions.
16730 */
16731static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016732xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016733 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016734 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016735{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016736 /*
16737 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016738 * 2 Circular groups are disallowed. That is, within the {particles}
16739 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016740 * is the group itself.
16741 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016742 if ((item == NULL) ||
16743 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16744 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016745 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016746 {
16747 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016748
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016749 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016750 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016751 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016752 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016753 * TODO: The error report is not adequate: this constraint
16754 * is defined for model groups but not definitions, but since
16755 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016756 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016757 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016758 */
16759 xmlSchemaPCustomErr(ctxt,
16760 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016761 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016762 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016763 "defined", xmlSchemaFormatQName(&str,
16764 item->targetNamespace, item->name));
16765 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016766 /*
16767 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016768 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016769 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016770 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016771 }
16772 }
16773}
16774
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016775/**
16776 * xmlSchemaGroupDefTermFixup:
16777 * @item: the particle with a model group definition as term
16778 * @ctxt: the parser context
16779 * @name: the name
16780 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016781 * Checks cos-all-limited.
16782 *
16783 * Assigns the model group of model group definitions to the "term"
16784 * of the referencing particle.
16785 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16786 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016787 */
16788static void
16789xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016790 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016791 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016792{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016793 if ((item == NULL) ||
16794 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16795 (item->children == NULL) ||
16796 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16797 (item->children->children == NULL))
16798 return;
16799 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016800 /*
16801 * TODO: Not nice, but we will anchor cos-all-limited here.
16802 */
16803 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16804 (item->maxOccurs != 1)) {
16805 /*
16806 * SPEC (1.2) "the {term} property of a particle with
16807 * {max occurs}=1which is part of a pair which constitutes the
16808 * {content type} of a complex type definition."
16809 */
16810 xmlSchemaPCustomErr(ctxt,
16811 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16812 NULL, (xmlSchemaTypePtr) item, item->node,
16813 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16814 "group is its term", NULL);
16815 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016816}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016817
16818/**
16819 * xmlSchemaGetCircAttrGrRef:
16820 * @ctxtGr: the searched attribute group
16821 * @attr: the current attribute list to be processed
16822 *
16823 * This one is intended to be used by
16824 * xmlSchemaCheckSRCAttributeGroupCircular only.
16825 *
16826 * Returns the circular attribute grou reference, otherwise NULL.
16827 */
16828static xmlSchemaAttributeGroupPtr
16829xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16830 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016831{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016832 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16833 int marked;
16834 /*
16835 * We will search for an attribute group reference which
16836 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016837 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016838 while (attr != NULL) {
16839 marked = 0;
16840 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16841 gr = (xmlSchemaAttributeGroupPtr) attr;
16842 if (gr->refItem != NULL) {
16843 if (gr->refItem == ctxtGr)
16844 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016845 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016846 XML_SCHEMAS_ATTRGROUP_MARKED) {
16847 attr = attr->next;
16848 continue;
16849 } else {
16850 /*
16851 * Mark as visited to avoid infinite recursion on
16852 * circular references not yet examined.
16853 */
16854 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16855 marked = 1;
16856 }
16857 }
16858 if (gr->attributes != NULL)
16859 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16860 /*
16861 * Unmark the visited group's attributes.
16862 */
16863 if (marked)
16864 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16865 if (circ != NULL)
16866 return (circ);
16867 }
16868 attr = attr->next;
16869 }
16870 return (NULL);
16871}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016872
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016873/**
16874 * xmlSchemaCheckSRCAttributeGroupCircular:
16875 * attrGr: the attribute group definition
16876 * @ctxt: the parser context
16877 * @name: the name
16878 *
16879 * Checks for circular references of attribute groups.
16880 */
16881static void
16882xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016883 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016884 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016885{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016886 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016887 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016888 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016889 * 3 Circular group reference is disallowed outside <redefine>.
16890 * That is, unless this element information item's parent is
16891 * <redefine>, then among the [children], if any, there must
16892 * not be an <attributeGroup> with ref [attribute] which resolves
16893 * to the component corresponding to this <attributeGroup>. Indirect
16894 * circularity is also ruled out. That is, when QName resolution
16895 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16896 * any <attributeGroup>s with a ref [attribute] among the [children],
16897 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016898 * which resolves to the component corresponding to this <attributeGroup>.
16899 */
16900 /*
16901 * Only global components can be referenced.
16902 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016903 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016904 (attrGr->attributes == NULL))
16905 return;
16906 else {
16907 xmlSchemaAttributeGroupPtr circ;
16908
16909 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16910 if (circ != NULL) {
16911 /*
16912 * TODO: Report the referenced attr group as QName.
16913 */
16914 xmlSchemaPCustomErr(ctxt,
16915 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16916 NULL, NULL, circ->node,
16917 "Circular reference to the attribute group '%s' "
16918 "defined", attrGr->name);
16919 /*
16920 * NOTE: We will cut the reference to avoid further
16921 * confusion of the processor.
16922 * BADSPEC: The spec should define how to process in this case.
16923 */
16924 circ->attributes = NULL;
16925 circ->refItem = NULL;
16926 }
16927 }
16928}
16929
16930/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016931 * xmlSchemaAttrGrpFixup:
16932 * @attrgrpDecl: the schema attribute definition
16933 * @ctxt: the schema parser context
16934 * @name: the attribute name
16935 *
16936 * Fixes finish doing the computations on the attributes definitions
16937 */
16938static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016939xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016940 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016941{
16942 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016943 name = attrgrp->name;
16944 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016945 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016946 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016947 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000016948
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016949 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016950 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016951 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016952 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000016953 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016954 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
16955 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000016956 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016957 return;
16958 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016959 attrgrp->refItem = ref;
16960 /*
16961 * Check for self reference!
16962 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016963 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000016964 attrgrp->attributes = ref->attributes;
16965 attrgrp->attributeWildcard = ref->attributeWildcard;
16966 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000016967}
16968
16969/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016970 * xmlSchemaAttrCheckValConstr:
16971 * @item: an schema attribute declaration/use
16972 * @ctxt: a schema parser context
16973 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016974 *
16975 *
16976 * Schema Component Constraint: Attribute Declaration Properties Correct
16977 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016978 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000016979 *
16980 * Fixes finish doing the computations on the attributes definitions
16981 */
16982static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016983xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016984 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016985 const xmlChar * name ATTRIBUTE_UNUSED)
16986{
16987
16988 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016989 * 2 if there is a {value constraint}, the canonical lexical
16990 * representation of its value must be ·valid· with respect
16991 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016992 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016993 if (item->defValue != NULL) {
16994 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016995
16996 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016997 PERROR_INT("xmlSchemaCheckAttrValConstr",
16998 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016999 return;
17000 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017001 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17002 item->node, item->subtypes, item->defValue, &(item->defVal),
17003 1, 1, 0);
17004 if (ret != 0) {
17005 if (ret < 0) {
17006 PERROR_INT("xmlSchemaAttrCheckValConstr",
17007 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017008 return;
17009 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017010 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17011 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17012 ret, item->node, (xmlSchemaTypePtr) item,
17013 "The value of the value constraint is not valid", NULL, NULL);
17014 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017015 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017016 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017017}
17018
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017019static xmlSchemaElementPtr
17020xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17021 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017022{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017023 xmlSchemaElementPtr ret;
17024
17025 if (SUBST_GROUP_AFF(ancestor) == NULL)
17026 return (NULL);
17027 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17028 return (ancestor);
17029
17030 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17031 return (NULL);
17032 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17033 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17034 SUBST_GROUP_AFF(ancestor));
17035 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17036
17037 return (ret);
17038}
17039
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017040/**
17041 * xmlSchemaCheckElemPropsCorrect:
17042 * @ctxt: a schema parser context
17043 * @decl: the element declaration
17044 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017045 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017046 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017047 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017048 *
17049 * STATUS:
17050 * missing: (6)
17051 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017052static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017053xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17054 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017055{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017056 int ret = 0;
17057 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017058 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017059 * SPEC (1) "The values of the properties of an element declaration
17060 * must be as described in the property tableau in The Element
17061 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17062 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017063 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017064 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017065 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017066
17067 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017068 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017069 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017070 * affiliation}, then {scope} must be global."
17071 */
17072 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17073 xmlSchemaPCustomErr(pctxt,
17074 XML_SCHEMAP_E_PROPS_CORRECT_3,
17075 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17076 "Only global element declarations can have a "
17077 "substitution group affiliation", NULL);
17078 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017079 }
17080 /*
17081 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17082 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017083 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017084 * property."
17085 */
17086 if (head == elemDecl)
17087 circ = head;
17088 else if (SUBST_GROUP_AFF(head) != NULL)
17089 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17090 else
17091 circ = NULL;
17092 if (circ != NULL) {
17093 xmlChar *strA = NULL, *strB = NULL;
17094
17095 xmlSchemaPCustomErrExt(pctxt,
17096 XML_SCHEMAP_E_PROPS_CORRECT_6,
17097 NULL, (xmlSchemaTypePtr) circ, circ->node,
17098 "The element declaration '%s' defines a circular "
17099 "substitution group to element declaration '%s'",
17100 xmlSchemaGetComponentQName(&strA, circ),
17101 xmlSchemaGetComponentQName(&strB, head),
17102 NULL);
17103 FREE_AND_NULL(strA)
17104 FREE_AND_NULL(strB)
17105 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17106 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017107 /*
17108 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017109 * the {type definition}
17110 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017111 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017112 * of the {substitution group exclusions} of the {substitution group
17113 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17114 * (if the {type definition} is complex) or as defined in
17115 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017116 * simple)."
17117 *
17118 * NOTE: {substitution group exclusions} means the values of the
17119 * attribute "final".
17120 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017121
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017122 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017123 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017124
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017125 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17126 set |= SUBSET_EXTENSION;
17127 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17128 set |= SUBSET_RESTRICTION;
17129
17130 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17131 ELEM_TYPE(head), set) != 0) {
17132 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17133
17134 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017135 xmlSchemaPCustomErrExt(pctxt,
17136 XML_SCHEMAP_E_PROPS_CORRECT_4,
17137 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017138 "The type definition '%s' was "
17139 "either rejected by the substitution group "
17140 "affiliation '%s', or not validly derived from its type "
17141 "definition '%s'",
17142 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017143 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017144 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017145 FREE_AND_NULL(strA)
17146 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017147 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017148 }
17149 }
17150 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017151 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017152 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017153 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017154 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017155 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017156 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017157 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017158 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017159 ((IS_SIMPLE_TYPE(typeDef) &&
17160 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017161 (IS_COMPLEX_TYPE(typeDef) &&
17162 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017163 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17164 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017165
17166 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17167 xmlSchemaPCustomErr(pctxt,
17168 XML_SCHEMAP_E_PROPS_CORRECT_5,
17169 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17170 "The type definition (or type definition's content type) is or "
17171 "is derived from ID; value constraints are not allowed in "
17172 "conjunction with such a type definition", NULL);
17173 } else if (elemDecl->value != NULL) {
17174 int vcret;
17175 xmlNodePtr node = NULL;
17176
17177 /*
17178 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17179 * representation of its value must be ·valid· with respect to the
17180 * {type definition} as defined in Element Default Valid (Immediate)
17181 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017182 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017183 if (typeDef == NULL) {
17184 xmlSchemaPErr(pctxt, elemDecl->node,
17185 XML_SCHEMAP_INTERNAL,
17186 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17187 "type is missing... skipping validation of "
17188 "the value constraint", NULL, NULL);
17189 return (-1);
17190 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017191 if (elemDecl->node != NULL) {
17192 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17193 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17194 BAD_CAST "fixed");
17195 else
17196 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17197 BAD_CAST "default");
17198 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017199 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17200 typeDef, elemDecl->value, &(elemDecl->defVal));
17201 if (vcret != 0) {
17202 if (vcret < 0) {
17203 PERROR_INT("xmlSchemaElemCheckValConstr",
17204 "failed to validate the value constraint of an "
17205 "element declaration");
17206 return (-1);
17207 }
17208 return (vcret);
17209 }
17210 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017211
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017212 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017213}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017214
17215/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017216 * xmlSchemaCheckElemSubstGroup:
17217 * @ctxt: a schema parser context
17218 * @decl: the element declaration
17219 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017220 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017221 * Schema Component Constraint:
17222 * Substitution Group (cos-equiv-class)
17223 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017224 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017225 * a list will be built for each subst. group head, holding all direct
17226 * referents to this head.
17227 * NOTE that this function needs:
17228 * 1. circular subst. groups to be checked beforehand
17229 * 2. the declaration's type to be derived from the head's type
17230 *
17231 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017232 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017233 */
17234static void
17235xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17236 xmlSchemaElementPtr elemDecl)
17237{
17238 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17239 /* SPEC (1) "Its {abstract} is false." */
17240 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17241 return;
17242 {
17243 xmlSchemaElementPtr head;
17244 xmlSchemaTypePtr headType, type;
17245 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017246 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017247 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17248 * {disallowed substitutions} as the blocking constraint, as defined in
17249 * Substitution Group OK (Transitive) (§3.3.6)."
17250 */
17251 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17252 head = SUBST_GROUP_AFF(head)) {
17253 set = 0;
17254 methSet = 0;
17255 /*
17256 * The blocking constraints.
17257 */
17258 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17259 continue;
17260 headType = head->subtypes;
17261 type = elemDecl->subtypes;
17262 if (headType == type)
17263 goto add_member;
17264 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17265 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17266 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17267 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17268 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017269 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017270 * "The set of all {derivation method}s involved in the
17271 * derivation of D's {type definition} from C's {type definition}
17272 * does not intersect with the union of the blocking constraint,
17273 * C's {prohibited substitutions} (if C is complex, otherwise the
17274 * empty set) and the {prohibited substitutions} (respectively the
17275 * empty set) of any intermediate {type definition}s in the
17276 * derivation of D's {type definition} from C's {type definition}."
17277 */
17278 /*
17279 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17280 * subst.head axis, the methSet does not need to be computed for
17281 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017282 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017283 /*
17284 * The set of all {derivation method}s involved in the derivation
17285 */
17286 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017287 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017288 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17289 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17290 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017291
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017292 if ((type->flags &
17293 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17294 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17295 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17296
17297 type = type->baseType;
17298 }
17299 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017300 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017301 * the head's type.
17302 */
17303 type = elemDecl->subtypes->baseType;
17304 while (type != NULL) {
17305 if (IS_COMPLEX_TYPE(type)) {
17306 if ((type->flags &
17307 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17308 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17309 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17310 if ((type->flags &
17311 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17312 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17313 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17314 } else
17315 break;
17316 if (type == headType)
17317 break;
17318 type = type->baseType;
17319 }
17320 if ((set != 0) &&
17321 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17322 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17323 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17324 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17325 continue;
17326 }
17327add_member:
17328 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17329 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17330 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17331 }
17332 }
17333}
17334
17335/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017336 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017337 * @item: an schema element declaration/particle
17338 * @ctxt: a schema parser context
17339 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017340 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017341 * Validates the value constraints of an element declaration.
17342 *
17343 * Fixes finish doing the computations on the element declarations.
17344 */
17345static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017346xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017347 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017348 const xmlChar * name ATTRIBUTE_UNUSED)
17349{
17350 if (elemDecl == NULL)
17351 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017352 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17353 return;
17354 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017355 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17356 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017357}
17358
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017359/**
17360 * xmlSchemaMiscRefFixup:
17361 * @item: an schema component
17362 * @ctxt: a schema parser context
17363 * @name: the internal name of the component
17364 *
17365 * Resolves references of misc. schema components.
17366 */
17367static void
17368xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017369 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017370 const xmlChar * name ATTRIBUTE_UNUSED)
17371{
17372 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017373 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017374 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17375 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17376 xmlSchemaTreeItemPtr refItem;
17377 /*
17378 * Resolve the reference.
17379 */
17380 item->children = NULL;
17381 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17382 ref->itemType, ref->name, ref->targetNamespace);
17383 if (refItem == NULL) {
17384 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017385 NULL, GET_NODE(item), "ref", ref->name,
17386 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017387 } else {
17388 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17389 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017390 * NOTE that we will assign the model group definition
17391 * itself to the "term" of the particle. This will ease
17392 * the check for circular model group definitions. After
17393 * that the "term" will be assigned the model group of the
17394 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017395 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017396 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017397 } else
17398 item->children = refItem;
17399 }
17400 }
17401 }
17402}
17403
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017404static int
17405xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17406 xmlSchemaValPtr y)
17407{
17408 xmlSchemaTypePtr tx, ty, ptx, pty;
17409 int ret;
17410
17411 while (x != NULL) {
17412 /* Same types. */
17413 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17414 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17415 ptx = xmlSchemaGetPrimitiveType(tx);
17416 pty = xmlSchemaGetPrimitiveType(ty);
17417 /*
17418 * (1) if a datatype T' is ·derived· by ·restriction· from an
17419 * atomic datatype T then the ·value space· of T' is a subset of
17420 * the ·value space· of T. */
17421 /*
17422 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17423 * from a common atomic ancestor T then the ·value space·s of T'
17424 * and T'' may overlap.
17425 */
17426 if (ptx != pty)
17427 return(0);
17428 /*
17429 * We assume computed values to be normalized, so do a fast
17430 * string comparison for string based types.
17431 */
17432 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17433 IS_ANY_SIMPLE_TYPE(ptx)) {
17434 if (! xmlStrEqual(
17435 xmlSchemaValueGetAsString(x),
17436 xmlSchemaValueGetAsString(y)))
17437 return (0);
17438 } else {
17439 ret = xmlSchemaCompareValuesWhtsp(
17440 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17441 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17442 if (ret == -2)
17443 return(-1);
17444 if (ret != 0)
17445 return(0);
17446 }
17447 /*
17448 * Lists.
17449 */
17450 x = xmlSchemaValueGetNext(x);
17451 if (x != NULL) {
17452 y = xmlSchemaValueGetNext(y);
17453 if (y == NULL)
17454 return (0);
17455 } else if (xmlSchemaValueGetNext(y) != NULL)
17456 return (0);
17457 else
17458 return (1);
17459 }
17460 return (0);
17461}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017462
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017463/**
17464 * xmlSchemaAttrFixup:
17465 * @item: an schema attribute declaration/use.
17466 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017467 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017468 *
17469 * Fixes finish doing the computations on attribute declarations/uses.
17470 */
17471static void
17472xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017473 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017474 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017475{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017476 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017477 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017478 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017479 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017480 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017481 * The simple type definition corresponding to the <simpleType> element
17482 * information item in the [children], if present, otherwise the simple
17483 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017484 * [attribute], if present, otherwise the ·simple ur-type definition·.
17485 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017486 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017487 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017488 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17489 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017490 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017491 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017492 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017493
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017494 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17495 item->typeNs);
17496 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017497 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017498 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017499 (xmlSchemaTypePtr) item, item->node,
17500 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017501 XML_SCHEMA_TYPE_SIMPLE, NULL);
17502 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017503 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017504
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017505 } else if (item->ref != NULL) {
17506 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017507
Daniel Veillardc0826a72004-08-10 14:17:33 +000017508 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017509 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017510 * attribute declaration.
17511 */
17512 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017513 * TODO: Evaluate, what errors could occur if the declaration is not
17514 * found. It might be possible that the "typefixup" might crash if
17515 * no ref declaration was found.
17516 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017517 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017518 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017519 xmlSchemaPResCompAttrErr(ctxt,
17520 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017521 (xmlSchemaTypePtr) item, item->node,
17522 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017523 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017524 return;
17525 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017526 item->refDecl = decl;
17527 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017528 item->subtypes = decl->subtypes;
17529 /*
17530 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017531 * au-props-correct.2: If the {attribute declaration} has a fixed
17532 * {value constraint}, then if the attribute use itself has a
17533 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017534 * that of the {attribute declaration}'s {value constraint}.
17535 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017536 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017537 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017538 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017539 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017540 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17541 NULL, NULL, item->node,
17542 "The attribute declaration has a 'fixed' value constraint "
17543 ", thus it must be 'fixed' in attribute use as well",
17544 NULL);
17545 } else {
17546 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17547 xmlSchemaPCustomErr(ctxt,
17548 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17549 NULL, NULL, item->node,
17550 "The 'fixed' value constraint of the attribute use "
17551 "must match the attribute declaration's value "
17552 "constraint '%s'",
17553 decl->defValue);
17554 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017555 }
17556 /*
17557 * FUTURE: One should change the values of the attr. use
17558 * if ever validation should be attempted even if the
17559 * schema itself was not fully valid.
17560 */
17561 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017562 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017563 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17564 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017565}
17566
17567/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017568 * xmlSchemaResolveIDCKeyRef:
17569 * @idc: the identity-constraint definition
17570 * @ctxt: the schema parser context
17571 * @name: the attribute name
17572 *
17573 * Resolve keyRef references to key/unique IDCs.
17574 */
17575static void
17576xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017577 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017578 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017579{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017580 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17581 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017582 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017583 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017584 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017585 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017586 idc->ref->targetNamespace);
17587 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017588 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017589 * TODO: It is actually not an error to fail to resolve.
17590 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017591 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017592 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017593 (xmlSchemaTypePtr) idc, idc->node,
17594 "refer", idc->ref->name,
17595 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017596 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17597 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017598 } else {
17599 if (idc->nbFields !=
17600 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17601 xmlChar *str = NULL;
17602 xmlSchemaIDCPtr refer;
17603
17604 refer = (xmlSchemaIDCPtr) idc->ref->item;
17605 /*
17606 * SPEC c-props-correct(2)
17607 * "If the {identity-constraint category} is keyref,
17608 * the cardinality of the {fields} must equal that of
17609 * the {fields} of the {referenced key}.
17610 */
17611 xmlSchemaPCustomErr(pctxt,
17612 XML_SCHEMAP_C_PROPS_CORRECT,
17613 NULL, (xmlSchemaTypePtr) idc, idc->node,
17614 "The cardinality of the keyref differs from the "
17615 "cardinality of the referenced key '%s'",
17616 xmlSchemaFormatQName(&str, refer->targetNamespace,
17617 refer->name)
17618 );
17619 FREE_AND_NULL(str)
17620 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017621 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017622 }
17623}
17624
17625/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017626 * xmlSchemaParse:
17627 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017628 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017629 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017630 * XML Shema struture which can be used to validate instances.
17631 * *WARNING* this interface is highly subject to change
17632 *
17633 * Returns the internal XML Schema structure built from the resource or
17634 * NULL in case of error
17635 */
17636xmlSchemaPtr
17637xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17638{
17639 xmlSchemaPtr ret = NULL;
17640 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017641 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017642 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017643
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017644 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017645 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017646 * the API; i.e. not automatically by the validated instance document.
17647 */
17648
Daniel Veillard4255d502002-04-16 15:50:10 +000017649 xmlSchemaInitTypes();
17650
Daniel Veillard6045c902002-10-09 21:13:59 +000017651 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017652 return (NULL);
17653
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017654 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017655 ctxt->counter = 0;
17656 ctxt->container = NULL;
17657
17658 /*
17659 * First step is to parse the input document into an DOM/Infoset
17660 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017661 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017662 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017663 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017664 if (doc == NULL) {
17665 xmlSchemaPErr(ctxt, NULL,
17666 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017667 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017668 ctxt->URL, NULL);
17669 return (NULL);
17670 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017671 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017672 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17673 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017674 if (doc == NULL) {
17675 xmlSchemaPErr(ctxt, NULL,
17676 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017677 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017678 NULL, NULL);
17679 return (NULL);
17680 }
17681 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017682 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017683 } else if (ctxt->doc != NULL) {
17684 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017685 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017686 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017687 xmlSchemaPErr(ctxt, NULL,
17688 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017689 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017690 NULL, NULL);
17691 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017692 }
17693
17694 /*
17695 * Then extract the root and Schema parse it
17696 */
17697 root = xmlDocGetRootElement(doc);
17698 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017699 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17700 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017701 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017702 if (!preserve) {
17703 xmlFreeDoc(doc);
17704 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017705 return (NULL);
17706 }
17707
17708 /*
17709 * Remove all the blank text nodes
17710 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017711 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017712
17713 /*
17714 * Then do the parsing for good
17715 */
17716 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017717 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017718 if (!preserve) {
17719 xmlFreeDoc(doc);
17720 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017721 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017722 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017723 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017724 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017725 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017726 ctxt->ctxtType = NULL;
17727 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017728
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017729 /*
17730 * Resolve base types of simple/complex types.
17731 */
17732 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017733
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017734 if (ctxt->nberrors != 0)
17735 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017736
17737 if (ret->volatiles != NULL) {
17738 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17739 int i;
17740 xmlSchemaTreeItemPtr item;
17741
17742 for (i = 0; i < list->nbItems; i++) {
17743 item = (xmlSchemaTreeItemPtr) list->items[i];
17744 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17745 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017746 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017747 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017748 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017749 * Then fixup all attributes declarations
17750 */
17751 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017752 /*
17753 * Then fixup all attributes group declarations
17754 */
17755 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17756 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017757 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017758 * Resolve identity-constraint keyRefs.
17759 */
17760 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017761 /*
17762 * Check type defnitions for circular references.
17763 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017764 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017765 xmlSchemaCheckTypeDefCircular, ctxt);
17766 /*
17767 * Check model groups defnitions for circular references.
17768 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017769 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017770 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017771 /*
17772 * Set the "term" of particles pointing to model group definitions
17773 * to the contained model group.
17774 */
17775 if (ret->volatiles != NULL) {
17776 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17777 int i;
17778 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017779
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017780 for (i = 0; i < list->nbItems; i++) {
17781 item = (xmlSchemaParticlePtr) list->items[i];
17782 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17783 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17784 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017785 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017786 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017787 * Check attribute groups for circular references.
17788 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017789 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17790 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017791 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017792 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017793 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017794 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017795 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017796 /*
17797 * We will stop here if the schema was not valid to avoid internal errors
17798 * on missing sub-components. This is not conforming to the spec, since it
17799 * allows missing components, but it might make further processing crash.
17800 * So see it as a very strict handling, which might be made more lax in the
17801 * future.
17802 */
17803 if (ctxt->nberrors != 0)
17804 goto exit;
17805 /*
17806 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017807 */
17808 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017809 /*
17810 * Validate the value constraint of attribute declarations/uses.
17811 */
17812 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017813 /*
17814 * Validate the value constraint of element declarations.
17815 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017816 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017817
17818 if (ctxt->nberrors != 0)
17819 goto exit;
17820
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017821 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017822 * TODO: cos-element-consistent, cos-all-limited
17823 *
17824 * Then build the content model for all complex types
17825 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017826 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017827 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017828
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017829exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017830 if (ctxt->nberrors != 0) {
17831 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017832 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017833 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017834 return (ret);
17835}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017836
Daniel Veillard4255d502002-04-16 15:50:10 +000017837/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017838 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017839 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017840 * @err: the error callback
17841 * @warn: the warning callback
17842 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017843 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017844 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017845 */
17846void
17847xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017848 xmlSchemaValidityErrorFunc err,
17849 xmlSchemaValidityWarningFunc warn, void *ctx)
17850{
Daniel Veillard4255d502002-04-16 15:50:10 +000017851 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017852 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017853 ctxt->error = err;
17854 ctxt->warning = warn;
17855 ctxt->userData = ctx;
17856}
17857
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017858/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017859 * xmlSchemaGetParserErrors:
17860 * @ctxt: a XMl-Schema parser context
17861 * @err: the error callback result
17862 * @warn: the warning callback result
17863 * @ctx: contextual data for the callbacks result
17864 *
17865 * Get the callback information used to handle errors for a parser context
17866 *
17867 * Returns -1 in case of failure, 0 otherwise
17868 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017869int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017870xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17871 xmlSchemaValidityErrorFunc * err,
17872 xmlSchemaValidityWarningFunc * warn, void **ctx)
17873{
17874 if (ctxt == NULL)
17875 return(-1);
17876 if (err != NULL)
17877 *err = ctxt->error;
17878 if (warn != NULL)
17879 *warn = ctxt->warning;
17880 if (ctx != NULL)
17881 *ctx = ctxt->userData;
17882 return(0);
17883}
17884
17885/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017886 * xmlSchemaFacetTypeToString:
17887 * @type: the facet type
17888 *
17889 * Convert the xmlSchemaTypeType to a char string.
17890 *
17891 * Returns the char string representation of the facet type if the
17892 * type is a facet and an "Internal Error" string otherwise.
17893 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017894static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017895xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17896{
17897 switch (type) {
17898 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017899 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017900 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017901 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017902 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017903 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017904 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017905 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017906 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017907 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017908 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017909 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017910 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017911 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017912 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017913 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017914 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017915 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017916 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017917 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017918 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017919 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017920 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017921 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017922 default:
17923 break;
17924 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017925 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017926}
17927
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017928static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017929xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17930{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017931 /*
17932 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017933 * from xsd:string.
17934 */
17935 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017936 /*
17937 * Note that we assume a whitespace of preserve for anySimpleType.
17938 */
17939 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17940 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17941 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017942 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017943 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017944 else {
17945 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017946 * For all ·atomic· datatypes other than string (and types ·derived·
17947 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000017948 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017949 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017950 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017951 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017952 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017953 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017954 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017955 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017956 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017957 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
17958 } else if (VARIETY_UNION(type)) {
17959 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
17960 } else if (VARIETY_ATOMIC(type)) {
17961 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
17962 return (XML_SCHEMA_WHITESPACE_PRESERVE);
17963 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
17964 return (XML_SCHEMA_WHITESPACE_REPLACE);
17965 else
17966 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017967 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017968 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017969}
17970
Daniel Veillard4255d502002-04-16 15:50:10 +000017971/************************************************************************
17972 * *
17973 * Simple type validation *
17974 * *
17975 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000017976
Daniel Veillard4255d502002-04-16 15:50:10 +000017977
17978/************************************************************************
17979 * *
17980 * DOM Validation code *
17981 * *
17982 ************************************************************************/
17983
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017984static void
17985xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
17986{
17987 int i, nbItems;
17988 xmlSchemaTypePtr item, *items;
17989
17990
17991 /*
17992 * During the Assemble of the schema ctxt->curItems has
17993 * been filled with the relevant new items. Fix those up.
17994 */
17995 nbItems = ctxt->assemble->nbItems;
17996 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017997
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017998 for (i = 0; i < nbItems; i++) {
17999 item = items[i];
18000 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018001 case XML_SCHEMA_TYPE_COMPLEX:
18002 case XML_SCHEMA_TYPE_SIMPLE:
18003 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18004 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018005 case XML_SCHEMA_TYPE_ATTRIBUTE:
18006 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18007 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018008 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018009 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018010 ctxt, NULL);
18011 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018012 case XML_SCHEMA_TYPE_PARTICLE:
18013 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018014 break;
18015 case XML_SCHEMA_TYPE_IDC_KEY:
18016 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18017 case XML_SCHEMA_TYPE_IDC_KEYREF:
18018 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18019 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018020 default:
18021 break;
18022 }
18023 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018024 if (ctxt->nberrors != 0)
18025 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018026 /*
18027 * Circularity checks.
18028 */
18029 for (i = 0; i < nbItems; i++) {
18030 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018031 switch (item->type) {
18032 case XML_SCHEMA_TYPE_COMPLEX:
18033 case XML_SCHEMA_TYPE_SIMPLE:
18034 xmlSchemaCheckTypeDefCircular(
18035 (xmlSchemaTypePtr) item, ctxt, NULL);
18036 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018037 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018038 xmlSchemaCheckGroupDefCircular(
18039 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018040 break;
18041 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18042 xmlSchemaCheckAttributeGroupCircular(
18043 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18044 break;
18045 default:
18046 break;
18047 }
18048 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018049 if (ctxt->nberrors != 0)
18050 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018051 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018052 * Set the "term" of particles pointing to model group definitions
18053 * to the contained model group.
18054 */
18055 for (i = 0; i < nbItems; i++) {
18056 item = items[i];
18057 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18058 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018059 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018060 XML_SCHEMA_TYPE_GROUP)) {
18061 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18062 ctxt, NULL);
18063 }
18064 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018065 if (ctxt->nberrors != 0)
18066 return;
18067 for (i = 0; i < nbItems; i++) {
18068 item = items[i];
18069 switch (item->type) {
18070 case XML_SCHEMA_TYPE_ELEMENT:
18071 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18072 NULL, NULL, NULL);
18073 break;
18074 default:
18075 break;
18076 }
18077 }
18078 if (ctxt->nberrors != 0)
18079 return;
18080
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018081 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018082 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018083 */
18084 for (i = 0; i < nbItems; i++) {
18085 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018086 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018087 case XML_SCHEMA_TYPE_SIMPLE:
18088 case XML_SCHEMA_TYPE_COMPLEX:
18089 xmlSchemaTypeFixup(item, ctxt, NULL);
18090 break;
18091 default:
18092 break;
18093 }
18094 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018095 if (ctxt->nberrors != 0)
18096 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018097 /*
18098 * Validate value contraint values.
18099 */
18100 for (i = 0; i < nbItems; i++) {
18101 item = items[i];
18102 switch (item->type) {
18103 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018104 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18105 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018106 break;
18107 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018108 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018109 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018110 break;
18111 default:
18112 break;
18113 }
18114 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018115 if (ctxt->nberrors != 0)
18116 return;
18117 /*
18118 * Build the content model for complex types.
18119 */
18120 for (i = 0; i < nbItems; i++) {
18121 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018122 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018123 case XML_SCHEMA_TYPE_COMPLEX:
18124 xmlSchemaBuildContentModel(item, ctxt, NULL);
18125 break;
18126 default:
18127 break;
18128 }
18129 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018130}
18131
18132/**
18133 * xmlSchemaAssembleByLocation:
18134 * @pctxt: a schema parser context
18135 * @vctxt: a schema validation context
18136 * @schema: the existing schema
18137 * @node: the node that fired the assembling
18138 * @nsName: the namespace name of the new schema
18139 * @location: the location of the schema
18140 *
18141 * Expands an existing schema by an additional schema.
18142 *
18143 * Returns 0 if the new schema is correct, a positive error code
18144 * number otherwise and -1 in case of an internal or API error.
18145 */
18146static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018147xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018148 xmlSchemaPtr schema,
18149 xmlNodePtr node,
18150 const xmlChar *nsName,
18151 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018152{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018153 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018154 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018155 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018156 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018157 xmlSchemaParserCtxtPtr pctxt;
18158
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018159 /*
18160 * This should be used:
18161 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018162 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018163 * 3. if requested via the API
18164 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018165 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018166 return (-1);
18167 /*
18168 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018169 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018170 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018171 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18172 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018173 pctxt = vctxt->pctxt;
18174 /*
18175 * Set the counter to produce unique names for anonymous items.
18176 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018177 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018178 /*
18179 * Acquire the schema document.
18180 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018181 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18182 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018183 if (ret != 0) {
18184 if (doc != NULL)
18185 xmlFreeDoc(doc);
18186 } else if (doc != NULL) {
18187 docElem = xmlDocGetRootElement(doc);
18188 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018189 * Create new assemble info.
18190 */
18191 if (pctxt->assemble == NULL) {
18192 pctxt->assemble = xmlSchemaNewAssemble();
18193 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018194 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018195 "Memory error: xmlSchemaAssembleByLocation, "
18196 "allocating assemble info", NULL);
18197 xmlFreeDoc(doc);
18198 return (-1);
18199 }
18200 }
18201 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018202 * Save and reset the context & schema.
18203 */
18204 oldflags = schema->flags;
18205 oldtns = schema->targetNamespace;
18206 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018207 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018208
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018209 xmlSchemaClearSchemaDefaults(schema);
18210 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018211 if ((targetNs != NULL) &&
18212 xmlStrEqual(targetNs, xmlSchemaNs)) {
18213 /*
18214 * We are parsing the schema for schema!
18215 */
18216 vctxt->pctxt->isS4S = 1;
18217 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018218 /* schema->nbCurItems = 0; */
18219 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018220 pctxt->ctxtType = NULL;
18221 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018222
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018223 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18224 if (pctxt->nberrors != 0) {
18225 vctxt->nberrors += pctxt->nberrors;
18226 goto finally;
18227 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018228 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018229 if (pctxt->nberrors != 0) {
18230 vctxt->nberrors += pctxt->nberrors;
18231 goto finally;
18232 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018233 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018234 if (pctxt->nberrors != 0)
18235 vctxt->nberrors += pctxt->nberrors;
18236finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018237 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018238 * Set the counter of items.
18239 */
18240 schema->counter = pctxt->counter;
18241 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018242 * Free the list of assembled components.
18243 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018244 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018245 /*
18246 * Restore the context & schema.
18247 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018248 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018249 schema->flags = oldflags;
18250 schema->targetNamespace = oldtns;
18251 schema->doc = olddoc;
18252 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018253 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018254 return (ret);
18255}
18256
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018257static xmlSchemaAttrInfoPtr
18258xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18259 int metaType)
18260{
18261 if (vctxt->nbAttrInfos == 0)
18262 return (NULL);
18263 {
18264 int i;
18265 xmlSchemaAttrInfoPtr iattr;
18266
18267 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18268 iattr = vctxt->attrInfos[i];
18269 if (iattr->metaType == metaType)
18270 return (iattr);
18271 }
18272
18273 }
18274 return (NULL);
18275}
18276
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018277/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018278 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018279 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018280 *
18281 * Expands an existing schema by an additional schema using
18282 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18283 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18284 * must be set to 1.
18285 *
18286 * Returns 0 if the new schema is correct, a positive error code
18287 * number otherwise and -1 in case of an internal or API error.
18288 */
18289static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018290xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018291{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018292 const xmlChar *cur, *end;
18293 const xmlChar *nsname = NULL, *location;
18294 int count = 0;
18295 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018296 xmlSchemaAttrInfoPtr iattr;
18297
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018298 /*
18299 * Parse the value; we will assume an even number of values
18300 * to be given (this is how Xerces and XSV work).
18301 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018302 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18303 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18304 if (iattr == NULL)
18305 xmlSchemaGetMetaAttrInfo(vctxt,
18306 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18307 if (iattr == NULL)
18308 return (0);
18309 cur = iattr->value;
18310 do {
18311 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018312 /*
18313 * Get the namespace name.
18314 */
18315 while (IS_BLANK_CH(*cur))
18316 cur++;
18317 end = cur;
18318 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18319 end++;
18320 if (end == cur)
18321 break;
18322 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018323 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018324 cur = end;
18325 }
18326 /*
18327 * Get the URI.
18328 */
18329 while (IS_BLANK_CH(*cur))
18330 cur++;
18331 end = cur;
18332 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18333 end++;
18334 if (end == cur)
18335 break;
18336 count++;
18337 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018338 cur = end;
18339 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18340 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018341 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018342 VERROR_INT("xmlSchemaAssembleByXSI",
18343 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018344 return (-1);
18345 }
18346 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018347 return (ret);
18348}
18349
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018350#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018351
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018352static const xmlChar *
18353xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18354 const xmlChar *prefix)
18355{
18356 if (vctxt->sax != NULL) {
18357 int i, j;
18358 xmlSchemaNodeInfoPtr inode;
18359
18360 for (i = vctxt->depth; i >= 0; i--) {
18361 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18362 inode = vctxt->elemInfos[i];
18363 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18364 if (((prefix == NULL) &&
18365 (inode->nsBindings[j] == NULL)) ||
18366 ((prefix != NULL) && xmlStrEqual(prefix,
18367 inode->nsBindings[j]))) {
18368
18369 /*
18370 * Note that the namespace bindings are already
18371 * in a string dict.
18372 */
18373 return (inode->nsBindings[j+1]);
18374 }
18375 }
18376 }
18377 }
18378 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018379#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018380 } else if (vctxt->reader != NULL) {
18381 xmlChar *nsName;
18382
18383 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18384 if (nsName != NULL) {
18385 const xmlChar *ret;
18386
18387 VAL_CREATE_DICT;
18388 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18389 xmlFree(nsName);
18390 return (ret);
18391 } else
18392 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018393#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018394 } else {
18395 xmlNsPtr ns;
18396
18397 if ((vctxt->inode->node == NULL) ||
18398 (vctxt->inode->node->doc == NULL)) {
18399 VERROR_INT("xmlSchemaLookupNamespace",
18400 "no node or node's doc avaliable");
18401 return (NULL);
18402 }
18403 ns = xmlSearchNs(vctxt->inode->node->doc,
18404 vctxt->inode->node, prefix);
18405 if (ns != NULL)
18406 return (ns->href);
18407 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018408 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018409}
18410
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018411/*
18412* This one works on the schema of the validation context.
18413*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018414static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018415xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18416 xmlSchemaPtr schema,
18417 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018418 const xmlChar *value,
18419 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018420 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018421{
18422 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018423
18424 if (vctxt && (vctxt->schema == NULL)) {
18425 VERROR_INT("xmlSchemaValidateNotation",
18426 "a schema is needed on the validation context");
18427 return (-1);
18428 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018429 ret = xmlValidateQName(value, 1);
18430 if (ret != 0)
18431 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018432 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018433 xmlChar *localName = NULL;
18434 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018435
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018436 localName = xmlSplitQName2(value, &prefix);
18437 if (prefix != NULL) {
18438 const xmlChar *nsName = NULL;
18439
18440 if (vctxt != NULL)
18441 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18442 else if (node != NULL) {
18443 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18444 if (ns != NULL)
18445 nsName = ns->href;
18446 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018447 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018448 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018449 return (1);
18450 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018451 if (nsName == NULL) {
18452 xmlFree(prefix);
18453 xmlFree(localName);
18454 return (1);
18455 }
18456 if (xmlHashLookup2(schema->notaDecl, localName,
18457 nsName) != NULL) {
18458 if (valNeeded && (val != NULL)) {
18459 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18460 BAD_CAST xmlStrdup(nsName));
18461 if (*val == NULL)
18462 ret = -1;
18463 }
18464 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018465 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018466 xmlFree(prefix);
18467 xmlFree(localName);
18468 } else {
18469 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18470 if (valNeeded && (val != NULL)) {
18471 (*val) = xmlSchemaNewNOTATIONValue(
18472 BAD_CAST xmlStrdup(value), NULL);
18473 if (*val == NULL)
18474 ret = -1;
18475 }
18476 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018477 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018478 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018479 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018480 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018481}
18482
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018483/************************************************************************
18484 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018485 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018486 * *
18487 ************************************************************************/
18488
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018489/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018490 * xmlSchemaAugmentIDC:
18491 * @idcDef: the IDC definition
18492 *
18493 * Creates an augmented IDC definition item.
18494 *
18495 * Returns the item, or NULL on internal errors.
18496 */
18497static void
18498xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18499 xmlSchemaValidCtxtPtr vctxt)
18500{
18501 xmlSchemaIDCAugPtr aidc;
18502
18503 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18504 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018505 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018506 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18507 NULL);
18508 return;
18509 }
18510 aidc->bubbleDepth = -1;
18511 aidc->def = idcDef;
18512 aidc->next = NULL;
18513 if (vctxt->aidcs == NULL)
18514 vctxt->aidcs = aidc;
18515 else {
18516 aidc->next = vctxt->aidcs;
18517 vctxt->aidcs = aidc;
18518 }
18519}
18520
18521/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018522 * xmlSchemaIDCNewBinding:
18523 * @idcDef: the IDC definition of this binding
18524 *
18525 * Creates a new IDC binding.
18526 *
18527 * Returns the new binding in case of succeeded, NULL on internal errors.
18528 */
18529static xmlSchemaPSVIIDCBindingPtr
18530xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18531{
18532 xmlSchemaPSVIIDCBindingPtr ret;
18533
18534 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18535 sizeof(xmlSchemaPSVIIDCBinding));
18536 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018537 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018538 "allocating a PSVI IDC binding item", NULL);
18539 return (NULL);
18540 }
18541 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18542 ret->definition = idcDef;
18543 return (ret);
18544}
18545
18546/**
18547 * xmlSchemaIDCStoreNodeTableItem:
18548 * @vctxt: the WXS validation context
18549 * @item: the IDC node table item
18550 *
18551 * The validation context is used to store an IDC node table items.
18552 * They are stored to avoid copying them if IDC node-tables are merged
18553 * with corresponding parent IDC node-tables (bubbling).
18554 *
18555 * Returns 0 if succeeded, -1 on internal errors.
18556 */
18557static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018558xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018559 xmlSchemaPSVIIDCNodePtr item)
18560{
18561 /*
18562 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018563 */
18564 if (vctxt->idcNodes == NULL) {
18565 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018566 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18567 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018568 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018569 "allocating the IDC node table item list", NULL);
18570 return (-1);
18571 }
18572 vctxt->sizeIdcNodes = 20;
18573 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18574 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018575 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18576 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018577 sizeof(xmlSchemaPSVIIDCNodePtr));
18578 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018579 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018580 "re-allocating the IDC node table item list", NULL);
18581 return (-1);
18582 }
18583 }
18584 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018585
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018586 return (0);
18587}
18588
18589/**
18590 * xmlSchemaIDCStoreKey:
18591 * @vctxt: the WXS validation context
18592 * @item: the IDC key
18593 *
18594 * The validation context is used to store an IDC key.
18595 *
18596 * Returns 0 if succeeded, -1 on internal errors.
18597 */
18598static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018599xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018600 xmlSchemaPSVIIDCKeyPtr key)
18601{
18602 /*
18603 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018604 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018605 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018606 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018607 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18608 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018609 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018610 "allocating the IDC key storage list", NULL);
18611 return (-1);
18612 }
18613 vctxt->sizeIdcKeys = 40;
18614 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18615 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018616 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18617 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018618 sizeof(xmlSchemaPSVIIDCKeyPtr));
18619 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018620 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018621 "re-allocating the IDC key storage list", NULL);
18622 return (-1);
18623 }
18624 }
18625 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018626
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018627 return (0);
18628}
18629
18630/**
18631 * xmlSchemaIDCAppendNodeTableItem:
18632 * @bind: the IDC binding
18633 * @ntItem: the node-table item
18634 *
18635 * Appends the IDC node-table item to the binding.
18636 *
18637 * Returns 0 on success and -1 on internal errors.
18638 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018639static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018640xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18641 xmlSchemaPSVIIDCNodePtr ntItem)
18642{
18643 if (bind->nodeTable == NULL) {
18644 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018645 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018646 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18647 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018648 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018649 "allocating an array of IDC node-table items", NULL);
18650 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018651 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018652 } else if (bind->sizeNodes <= bind->nbNodes) {
18653 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018654 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18655 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018656 sizeof(xmlSchemaPSVIIDCNodePtr));
18657 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018658 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018659 "re-allocating an array of IDC node-table items", NULL);
18660 return(-1);
18661 }
18662 }
18663 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018664 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018665}
18666
18667/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018668 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018669 * @vctxt: the WXS validation context
18670 * @matcher: the IDC matcher
18671 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018672 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018673 * of the given matcher. If none found, a new one is created
18674 * and added to the IDC table.
18675 *
18676 * Returns an IDC binding or NULL on internal errors.
18677 */
18678static xmlSchemaPSVIIDCBindingPtr
18679xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18680 xmlSchemaIDCMatcherPtr matcher)
18681{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018682 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018683
18684 info = vctxt->elemInfos[matcher->depth];
18685
18686 if (info->idcTable == NULL) {
18687 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18688 if (info->idcTable == NULL)
18689 return (NULL);
18690 return(info->idcTable);
18691 } else {
18692 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018693
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018694 bind = info->idcTable;
18695 do {
18696 if (bind->definition == matcher->aidc->def)
18697 return(bind);
18698 if (bind->next == NULL) {
18699 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18700 if (bind->next == NULL)
18701 return (NULL);
18702 return(bind->next);
18703 }
18704 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018705 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018706 }
18707 return (NULL);
18708}
18709
18710/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018711 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018712 * @key: the IDC key
18713 *
18714 * Frees an IDC key together with its compiled value.
18715 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018716static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018717xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18718{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018719 if (key->val != NULL)
18720 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018721 xmlFree(key);
18722}
18723
18724/**
18725 * xmlSchemaIDCFreeBinding:
18726 *
18727 * Frees an IDC binding. Note that the node table-items
18728 * are not freed.
18729 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018730static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018731xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18732{
18733 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018734 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18735 int i;
18736 /*
18737 * Node-table items for keyrefs are not stored globally
18738 * to the validation context, since they are not bubbled.
18739 * We need to free them here.
18740 */
18741 for (i = 0; i < bind->nbNodes; i++) {
18742 xmlFree(bind->nodeTable[i]->keys);
18743 xmlFree(bind->nodeTable[i]);
18744 }
18745 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018746 xmlFree(bind->nodeTable);
18747 }
18748 xmlFree(bind);
18749}
18750
18751/**
18752 * xmlSchemaIDCFreeIDCTable:
18753 * @bind: the first IDC binding in the list
18754 *
18755 * Frees an IDC table, i.e. all the IDC bindings in the list.
18756 */
18757static void
18758xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18759{
18760 xmlSchemaPSVIIDCBindingPtr prev;
18761
18762 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018763 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018764 bind = bind->next;
18765 xmlSchemaIDCFreeBinding(prev);
18766 }
18767}
18768
18769/**
18770 * xmlSchemaIDCFreeMatcherList:
18771 * @matcher: the first IDC matcher in the list
18772 *
18773 * Frees a list of IDC matchers.
18774 */
18775static void
18776xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18777{
18778 xmlSchemaIDCMatcherPtr next;
18779
18780 while (matcher != NULL) {
18781 next = matcher->next;
18782 if (matcher->keySeqs != NULL) {
18783 int i;
18784 for (i = 0; i < matcher->sizeKeySeqs; i++)
18785 if (matcher->keySeqs[i] != NULL)
18786 xmlFree(matcher->keySeqs[i]);
18787 xmlFree(matcher->keySeqs);
18788 }
18789 xmlFree(matcher);
18790 matcher = next;
18791 }
18792}
18793
18794/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018795 * xmlSchemaIDCAddStateObject:
18796 * @vctxt: the WXS validation context
18797 * @matcher: the IDC matcher
18798 * @sel: the XPath information
18799 * @parent: the parent "selector" state object if any
18800 * @type: "selector" or "field"
18801 *
18802 * Creates/reuses and activates state objects for the given
18803 * XPath information; if the XPath expression consists of unions,
18804 * multiple state objects are created for every unioned expression.
18805 *
18806 * Returns 0 on success and -1 on internal errors.
18807 */
18808static int
18809xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18810 xmlSchemaIDCMatcherPtr matcher,
18811 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018812 int type)
18813{
18814 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018815
18816 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018817 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018818 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018819 if (vctxt->xpathStatePool != NULL) {
18820 sto = vctxt->xpathStatePool;
18821 vctxt->xpathStatePool = sto->next;
18822 sto->next = NULL;
18823 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018824 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018825 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018826 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018827 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18828 if (sto == NULL) {
18829 xmlSchemaVErrMemory(NULL,
18830 "allocating an IDC state object", NULL);
18831 return (-1);
18832 }
18833 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18834 }
18835 /*
18836 * Add to global list.
18837 */
18838 if (vctxt->xpathStates != NULL)
18839 sto->next = vctxt->xpathStates;
18840 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018841
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018842 /*
18843 * Free the old xpath validation context.
18844 */
18845 if (sto->xpathCtxt != NULL)
18846 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18847
18848 /*
18849 * Create a new XPath (pattern) validation context.
18850 */
18851 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18852 (xmlPatternPtr) sel->xpathComp);
18853 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018854 VERROR_INT("xmlSchemaIDCAddStateObject",
18855 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018856 return (-1);
18857 }
18858 sto->type = type;
18859 sto->depth = vctxt->depth;
18860 sto->matcher = matcher;
18861 sto->sel = sel;
18862 sto->nbHistory = 0;
18863
18864#if DEBUG_IDC
18865 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18866 sto->sel->xpath);
18867#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018868 return (0);
18869}
18870
18871/**
18872 * xmlSchemaXPathEvaluate:
18873 * @vctxt: the WXS validation context
18874 * @nodeType: the nodeType of the current node
18875 *
18876 * Evaluates all active XPath state objects.
18877 *
18878 * Returns the number of IC "field" state objects which resolved to
18879 * this node, 0 if none resolved and -1 on internal errors.
18880 */
18881static int
18882xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018883 xmlElementType nodeType)
18884{
18885 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018886 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018887
18888 if (vctxt->xpathStates == NULL)
18889 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018890
18891 if (nodeType == XML_ATTRIBUTE_NODE)
18892 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018893#if DEBUG_IDC
18894 {
18895 xmlChar *str = NULL;
18896 xmlGenericError(xmlGenericErrorContext,
18897 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018898 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18899 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018900 FREE_AND_NULL(str)
18901 }
18902#endif
18903 /*
18904 * Process all active XPath state objects.
18905 */
18906 first = vctxt->xpathStates;
18907 sto = first;
18908 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018909#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018910 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018911 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18912 sto->matcher->aidc->def->name, sto->sel->xpath);
18913 else
18914 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18915 sto->matcher->aidc->def->name, sto->sel->xpath);
18916#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018917 if (nodeType == XML_ELEMENT_NODE)
18918 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018919 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018920 else
18921 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018922 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018923
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018924 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018925 VERROR_INT("xmlSchemaXPathEvaluate",
18926 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018927 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018928 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018929 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018930 goto next_sto;
18931 /*
18932 * Full match.
18933 */
18934#if DEBUG_IDC
18935 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018936 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018937#endif
18938 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018939 * Register a match in the state object history.
18940 */
18941 if (sto->history == NULL) {
18942 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18943 if (sto->history == NULL) {
18944 xmlSchemaVErrMemory(NULL,
18945 "allocating the state object history", NULL);
18946 return(-1);
18947 }
18948 sto->sizeHistory = 10;
18949 } else if (sto->sizeHistory <= sto->nbHistory) {
18950 sto->sizeHistory *= 2;
18951 sto->history = (int *) xmlRealloc(sto->history,
18952 sto->sizeHistory * sizeof(int));
18953 if (sto->history == NULL) {
18954 xmlSchemaVErrMemory(NULL,
18955 "re-allocating the state object history", NULL);
18956 return(-1);
18957 }
18958 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018959 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018960
18961#ifdef DEBUG_IDC
18962 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
18963 vctxt->depth);
18964#endif
18965
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018966 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
18967 xmlSchemaIDCSelectPtr sel;
18968 /*
18969 * Activate state objects for the IDC fields of
18970 * the IDC selector.
18971 */
18972#if DEBUG_IDC
18973 xmlGenericError(xmlGenericErrorContext, "IDC: "
18974 "activating field states\n");
18975#endif
18976 sel = sto->matcher->aidc->def->fields;
18977 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018978 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
18979 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
18980 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018981 sel = sel->next;
18982 }
18983 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
18984 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018985 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018986 */
18987#if DEBUG_IDC
18988 xmlGenericError(xmlGenericErrorContext,
18989 "IDC: key found\n");
18990#endif
18991 /*
18992 * Notify that the character value of this node is
18993 * needed.
18994 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018995 if (resolved == 0) {
18996 if ((vctxt->inode->flags &
18997 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
18998 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
18999 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019000 resolved++;
19001 }
19002next_sto:
19003 if (sto->next == NULL) {
19004 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019005 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019006 */
19007 head = first;
19008 sto = vctxt->xpathStates;
19009 } else
19010 sto = sto->next;
19011 }
19012 return (resolved);
19013}
19014
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019015static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019016xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019017 xmlChar **buf,
19018 xmlSchemaPSVIIDCKeyPtr *seq,
19019 int count)
19020{
19021 int i, res;
19022 const xmlChar *value = NULL;
19023
19024 *buf = xmlStrdup(BAD_CAST "[");
19025 for (i = 0; i < count; i++) {
19026 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019027 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19028 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019029 if (res == 0)
19030 *buf = xmlStrcat(*buf, value);
19031 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019032 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19033 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019034 *buf = xmlStrcat(*buf, BAD_CAST "???");
19035 }
19036 if (i < count -1)
19037 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19038 else
19039 *buf = xmlStrcat(*buf, BAD_CAST "'");
19040 if (value != NULL) {
19041 xmlFree((xmlChar *) value);
19042 value = NULL;
19043 }
19044 }
19045 *buf = xmlStrcat(*buf, BAD_CAST "]");
19046
19047 return (BAD_CAST *buf);
19048}
19049
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019050/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019051 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019052 * @vctxt: the WXS validation context
19053 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019054 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019055 *
19056 * Processes and pops the history items of the IDC state objects.
19057 * IDC key-sequences are validated/created on IDC bindings.
19058 *
19059 * Returns 0 on success and -1 on internal errors.
19060 */
19061static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019062xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019063 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019064{
19065 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019066 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019067 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019068 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019069
19070 if (vctxt->xpathStates == NULL)
19071 return (0);
19072 sto = vctxt->xpathStates;
19073
19074#if DEBUG_IDC
19075 {
19076 xmlChar *str = NULL;
19077 xmlGenericError(xmlGenericErrorContext,
19078 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019079 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19080 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019081 FREE_AND_NULL(str)
19082 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019083#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019084 /*
19085 * Evaluate the state objects.
19086 */
19087 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019088 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19089 if (res == -1) {
19090 VERROR_INT("xmlSchemaXPathProcessHistory",
19091 "calling xmlStreamPop()");
19092 return (-1);
19093 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019094#if DEBUG_IDC
19095 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19096 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019097#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019098 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019099 goto deregister_check;
19100
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019101 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019102
19103 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019104 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019105 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019106 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019107 sto = sto->next;
19108 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019109 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019110 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19111 if (! IS_SIMPLE_TYPE(type)) {
19112 /*
19113 * Not qualified if the field resolves to a node of non
19114 * simple type.
19115 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019116 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19117 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019118 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19119 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019120 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019121
19122 sto->nbHistory--;
19123 goto deregister_check;
19124 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019125 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019126 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019127 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019128 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019129 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019130 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019131 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19132 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019133 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019134 sto->nbHistory--;
19135 goto deregister_check;
19136 } else {
19137 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19138 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019139 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019140
19141 /*
19142 * The key will be anchored on the matcher's list of
19143 * key-sequences. The position in this list is determined
19144 * by the target node's depth relative to the matcher's
19145 * depth of creation (i.e. the depth of the scope element).
19146 */
19147 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019148 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019149
19150 /*
19151 * Create/grow the array of key-sequences.
19152 */
19153 if (matcher->keySeqs == NULL) {
19154 if (pos > 9)
19155 matcher->sizeKeySeqs = pos * 2;
19156 else
19157 matcher->sizeKeySeqs = 10;
19158 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19159 xmlMalloc(matcher->sizeKeySeqs *
19160 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19161 if (matcher->keySeqs == NULL) {
19162 xmlSchemaVErrMemory(NULL,
19163 "allocating an array of key-sequences",
19164 NULL);
19165 return(-1);
19166 }
19167 memset(matcher->keySeqs, 0,
19168 matcher->sizeKeySeqs *
19169 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19170 } else if (pos >= matcher->sizeKeySeqs) {
19171 int i = matcher->sizeKeySeqs;
19172
19173 matcher->sizeKeySeqs *= 2;
19174 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19175 xmlRealloc(matcher->keySeqs,
19176 matcher->sizeKeySeqs *
19177 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019178 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019179 xmlSchemaVErrMemory(NULL,
19180 "reallocating an array of key-sequences",
19181 NULL);
19182 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019183 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019184 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019185 * The array needs to be NULLed.
19186 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019187 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019188 for (; i < matcher->sizeKeySeqs; i++)
19189 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019190 }
19191
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019192 /*
19193 * Get/create the key-sequence.
19194 */
19195 keySeq = matcher->keySeqs[pos];
19196 if (keySeq == NULL) {
19197 goto create_sequence;
19198 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019199 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019200 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019201 * cvc-identity-constraint:
19202 * 3 For each node in the ·target node set· all
19203 * of the {fields}, with that node as the context
19204 * node, evaluate to either an empty node-set or
19205 * a node-set with exactly one member, which must
19206 * have a simple type.
19207 *
19208 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019209 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019210 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19211 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019212 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019213 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019214 "with more than one member",
19215 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019216 sto->nbHistory--;
19217 goto deregister_check;
19218 } else {
19219 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019220 }
19221 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019222
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019223create_sequence:
19224 /*
19225 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019226 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019227 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19228 matcher->aidc->def->nbFields *
19229 sizeof(xmlSchemaPSVIIDCKeyPtr));
19230 if (keySeq == NULL) {
19231 xmlSchemaVErrMemory(NULL,
19232 "allocating an IDC key-sequence", NULL);
19233 return(-1);
19234 }
19235 memset(keySeq, 0, matcher->aidc->def->nbFields *
19236 sizeof(xmlSchemaPSVIIDCKeyPtr));
19237 matcher->keySeqs[pos] = keySeq;
19238create_key:
19239 /*
19240 * Created a key once per node only.
19241 */
19242 if (key == NULL) {
19243 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19244 sizeof(xmlSchemaPSVIIDCKey));
19245 if (key == NULL) {
19246 xmlSchemaVErrMemory(NULL,
19247 "allocating a IDC key", NULL);
19248 xmlFree(keySeq);
19249 matcher->keySeqs[pos] = NULL;
19250 return(-1);
19251 }
19252 /*
19253 * Consume the compiled value.
19254 */
19255 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019256 key->val = vctxt->inode->val;
19257 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019258 /*
19259 * Store the key in a global list.
19260 */
19261 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19262 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019263 return (-1);
19264 }
19265 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019266 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019267 }
19268 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019269
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019270 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19271 xmlSchemaPSVIIDCBindingPtr bind;
19272 xmlSchemaPSVIIDCNodePtr ntItem;
19273 xmlSchemaIDCMatcherPtr matcher;
19274 xmlSchemaIDCPtr idc;
19275 int pos, i, j, nbKeys;
19276 /*
19277 * Here we have the following scenario:
19278 * An IDC 'selector' state object resolved to a target node,
19279 * during the time this target node was in the
19280 * ancestor-or-self axis, the 'field' state object(s) looked
19281 * out for matching nodes to create a key-sequence for this
19282 * target node. Now we are back to this target node and need
19283 * to put the key-sequence, together with the target node
19284 * itself, into the node-table of the corresponding IDC
19285 * binding.
19286 */
19287 matcher = sto->matcher;
19288 idc = matcher->aidc->def;
19289 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019290 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019291 /*
19292 * Check if the matcher has any key-sequences at all, plus
19293 * if it has a key-sequence for the current target node.
19294 */
19295 if ((matcher->keySeqs == NULL) ||
19296 (matcher->sizeKeySeqs <= pos)) {
19297 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19298 goto selector_key_error;
19299 else
19300 goto selector_leave;
19301 }
19302
19303 keySeq = &(matcher->keySeqs[pos]);
19304 if (*keySeq == NULL) {
19305 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19306 goto selector_key_error;
19307 else
19308 goto selector_leave;
19309 }
19310
19311 for (i = 0; i < nbKeys; i++) {
19312 if ((*keySeq)[i] == NULL) {
19313 /*
19314 * Not qualified, if not all fields did resolve.
19315 */
19316 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19317 /*
19318 * All fields of a "key" IDC must resolve.
19319 */
19320 goto selector_key_error;
19321 }
19322 goto selector_leave;
19323 }
19324 }
19325 /*
19326 * All fields did resolve.
19327 */
19328
19329 /*
19330 * 4.1 If the {identity-constraint category} is unique(/key),
19331 * then no two members of the ·qualified node set· have
19332 * ·key-sequences· whose members are pairwise equal, as
19333 * defined by Equal in [XML Schemas: Datatypes].
19334 *
19335 * Get the IDC binding from the matcher and check for
19336 * duplicate key-sequences.
19337 */
19338 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19339 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19340 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019341 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019342
19343 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019344 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019345 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019346 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019347 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019348 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019349 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019350 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019351 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019352 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019353 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019354 if (res == -1) {
19355 return (-1);
19356 } else if (res == 0)
19357 break;
19358 }
19359 if (res == 1) {
19360 /*
19361 * Duplicate found.
19362 */
19363 break;
19364 }
19365 i++;
19366 } while (i < bind->nbNodes);
19367 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019368 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019369 /*
19370 * TODO: Try to report the key-sequence.
19371 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019372 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19373 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019374 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019375 "Duplicate key-sequence %s",
19376 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19377 (*keySeq), nbKeys), NULL);
19378 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019379 goto selector_leave;
19380 }
19381 }
19382 /*
19383 * Add a node-table item to the IDC binding.
19384 */
19385 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19386 sizeof(xmlSchemaPSVIIDCNode));
19387 if (ntItem == NULL) {
19388 xmlSchemaVErrMemory(NULL,
19389 "allocating an IDC node-table item", NULL);
19390 xmlFree(*keySeq);
19391 *keySeq = NULL;
19392 return(-1);
19393 }
19394 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19395
19396 /*
19397 * Store the node-table item on global list.
19398 */
19399 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19400 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19401 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019402 xmlFree(*keySeq);
19403 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019404 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019405 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019406 }
19407 /*
19408 * Init the node-table item. Consume the key-sequence.
19409 */
19410 ntItem->node = vctxt->node;
19411 ntItem->keys = *keySeq;
19412 *keySeq = NULL;
19413 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19414 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19415 /*
19416 * Free the item, since keyref items won't be
19417 * put on a global list.
19418 */
19419 xmlFree(ntItem->keys);
19420 xmlFree(ntItem);
19421 }
19422 return (-1);
19423 }
19424
19425 goto selector_leave;
19426selector_key_error:
19427 /*
19428 * 4.2.1 (KEY) The ·target node set· and the
19429 * ·qualified node set· are equal, that is, every
19430 * member of the ·target node set· is also a member
19431 * of the ·qualified node set· and vice versa.
19432 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019433 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19434 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019435selector_leave:
19436 /*
19437 * Free the key-sequence if not added to the IDC table.
19438 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019439 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019440 xmlFree(*keySeq);
19441 *keySeq = NULL;
19442 }
19443 } /* if selector */
19444
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019445 sto->nbHistory--;
19446
19447deregister_check:
19448 /*
19449 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019450 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019451 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019452#if DEBUG_IDC
19453 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19454 sto->sel->xpath);
19455#endif
19456 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019457 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019458 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019459 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019460 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019461 nextsto = sto->next;
19462 /*
19463 * Unlink from the list of active XPath state objects.
19464 */
19465 vctxt->xpathStates = sto->next;
19466 sto->next = vctxt->xpathStatePool;
19467 /*
19468 * Link it to the pool of reusable state objects.
19469 */
19470 vctxt->xpathStatePool = sto;
19471 sto = nextsto;
19472 } else
19473 sto = sto->next;
19474 } /* while (sto != NULL) */
19475 return (0);
19476}
19477
19478/**
19479 * xmlSchemaIDCRegisterMatchers:
19480 * @vctxt: the WXS validation context
19481 * @elemDecl: the element declaration
19482 *
19483 * Creates helper objects to evaluate IDC selectors/fields
19484 * successively.
19485 *
19486 * Returns 0 if OK and -1 on internal errors.
19487 */
19488static int
19489xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19490 xmlSchemaElementPtr elemDecl)
19491{
19492 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19493 xmlSchemaIDCPtr idc, refIdc;
19494 xmlSchemaIDCAugPtr aidc;
19495
19496 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19497 if (idc == NULL)
19498 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019499
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019500#if DEBUG_IDC
19501 {
19502 xmlChar *str = NULL;
19503 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019504 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019505 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19506 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019507 FREE_AND_NULL(str)
19508 }
19509#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019510 if (vctxt->inode->idcMatchers != NULL) {
19511 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19512 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019513 return (-1);
19514 }
19515 do {
19516 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19517 /*
19518 * Since IDCs bubbles are expensive we need to know the
19519 * depth at which the bubbles should stop; this will be
19520 * the depth of the top-most keyref IDC. If no keyref
19521 * references a key/unique IDC, the bubbleDepth will
19522 * be -1, indicating that no bubbles are needed.
19523 */
19524 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19525 if (refIdc != NULL) {
19526 /*
19527 * Lookup the augmented IDC.
19528 */
19529 aidc = vctxt->aidcs;
19530 while (aidc != NULL) {
19531 if (aidc->def == refIdc)
19532 break;
19533 aidc = aidc->next;
19534 }
19535 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019536 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019537 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019538 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019539 return (-1);
19540 }
19541 if ((aidc->bubbleDepth == -1) ||
19542 (vctxt->depth < aidc->bubbleDepth))
19543 aidc->bubbleDepth = vctxt->depth;
19544 }
19545 }
19546 /*
19547 * Lookup the augmented IDC item for the IDC definition.
19548 */
19549 aidc = vctxt->aidcs;
19550 while (aidc != NULL) {
19551 if (aidc->def == idc)
19552 break;
19553 aidc = aidc->next;
19554 }
19555 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019556 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19557 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019558 return (-1);
19559 }
19560 /*
19561 * Create an IDC matcher for every IDC definition.
19562 */
19563 matcher = (xmlSchemaIDCMatcherPtr)
19564 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19565 if (matcher == NULL) {
19566 xmlSchemaVErrMemory(vctxt,
19567 "allocating an IDC matcher", NULL);
19568 return (-1);
19569 }
19570 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19571 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019572 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019573 else
19574 last->next = matcher;
19575 last = matcher;
19576
19577 matcher->type = IDC_MATCHER;
19578 matcher->depth = vctxt->depth;
19579 matcher->aidc = aidc;
19580#if DEBUG_IDC
19581 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19582#endif
19583 /*
19584 * Init the automaton state object.
19585 */
19586 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019587 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019588 return (-1);
19589
19590 idc = idc->next;
19591 } while (idc != NULL);
19592 return (0);
19593}
19594
19595/**
19596 * xmlSchemaBubbleIDCNodeTables:
19597 * @depth: the current tree depth
19598 *
19599 * Merges IDC bindings of an element at @depth into the corresponding IDC
19600 * bindings of its parent element. If a duplicate note-table entry is found,
19601 * both, the parent node-table entry and child entry are discarded from the
19602 * node-table of the parent.
19603 *
19604 * Returns 0 if OK and -1 on internal errors.
19605 */
19606static int
19607xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19608{
19609 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019610 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19611 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019612 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19613 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019614 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019615 int duplTop;
19616
19617 /*
19618 * The node table has the following sections:
19619 *
19620 * O --> old node-table entries (first)
19621 * O
19622 * + --> new node-table entries
19623 * +
19624 * % --> new duplicate node-table entries
19625 * %
19626 * # --> old duplicate node-table entries
19627 * # (last)
19628 *
19629 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019630 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019631 if (bind == NULL) {
19632 /* Fine, no table, no bubbles. */
19633 return (0);
19634 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019635
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019636 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19637 /*
19638 * Walk all bindings; create new or add to existing bindings.
19639 * Remove duplicate key-sequences.
19640 */
19641start_binding:
19642 while (bind != NULL) {
19643 /*
19644 * Skip keyref IDCs.
19645 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019646 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19647 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019648 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019649 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019650 /*
19651 * Check if the key/unique IDC table needs to be bubbled.
19652 */
19653 aidc = vctxt->aidcs;
19654 do {
19655 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019656 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019657 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019658 bind = bind->next;
19659 goto start_binding;
19660 }
19661 break;
19662 }
19663 aidc = aidc->next;
19664 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019665
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019666 if (parTable != NULL)
19667 parBind = *parTable;
19668 while (parBind != NULL) {
19669 /*
19670 * Search a matching parent binding for the
19671 * IDC definition.
19672 */
19673 if (parBind->definition == bind->definition) {
19674
19675 /*
19676 * Compare every node-table entry of the child node,
19677 * i.e. the key-sequence within, ...
19678 */
19679 oldNum = parBind->nbNodes; /* Skip newly added items. */
19680 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019681 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019682
19683 for (i = 0; i < bind->nbNodes; i++) {
19684 node = bind->nodeTable[i];
19685 if (node == NULL)
19686 continue;
19687 /*
19688 * ...with every key-sequence of the parent node, already
19689 * evaluated to be a duplicate key-sequence.
19690 */
19691 if (parBind->nbDupls != 0) {
19692 j = bind->nbNodes + newDupls;
19693 while (j < duplTop) {
19694 parNode = parBind->nodeTable[j];
19695 for (k = 0; k < bind->definition->nbFields; k++) {
19696 key = node->keys[k];
19697 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019698 ret = xmlSchemaAreValuesEqual(key->val,
19699 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019700 if (ret == -1) {
19701 /* TODO: Internal error */
19702 return(-1);
19703 } else if (ret == 0)
19704 break;
19705
19706 }
19707 if (ret == 1)
19708 /* Duplicate found. */
19709 break;
19710 j++;
19711 }
19712 if (j != duplTop) {
19713 /* Duplicate found. */
19714 continue;
19715 }
19716 }
19717 /*
19718 * ... and with every key-sequence of the parent node.
19719 */
19720 j = 0;
19721 while (j < oldNum) {
19722 parNode = parBind->nodeTable[j];
19723 /*
19724 * Compare key by key.
19725 */
19726 for (k = 0; k < parBind->definition->nbFields; k++) {
19727 key = node->keys[k];
19728 parKey = parNode->keys[k];
19729
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019730 ret = xmlSchemaAreValuesEqual(key->val,
19731 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019732 if (ret == -1) {
19733 /* TODO: Internal error */
19734 } else if (ret == 0)
19735 break;
19736
19737 }
19738 if (ret == 1)
19739 /*
19740 * The key-sequences are equal.
19741 */
19742 break;
19743 j++;
19744 }
19745 if (j != oldNum) {
19746 /*
19747 * Handle duplicates.
19748 */
19749 newDupls++;
19750 oldNum--;
19751 parBind->nbNodes--;
19752 /*
19753 * Move last old item to pos of duplicate.
19754 */
19755 parBind->nodeTable[j] =
19756 parBind->nodeTable[oldNum];
19757
19758 if (parBind->nbNodes != oldNum) {
19759 /*
19760 * If new items exist, move last new item to
19761 * last of old items.
19762 */
19763 parBind->nodeTable[oldNum] =
19764 parBind->nodeTable[parBind->nbNodes];
19765 }
19766 /*
19767 * Move duplicate to last pos of new/old items.
19768 */
19769 parBind->nodeTable[parBind->nbNodes] = parNode;
19770
19771 } else {
19772 /*
19773 * Add the node-table entry (node and key-sequence) of
19774 * the child node to the node table of the parent node.
19775 */
19776 if (parBind->nodeTable == NULL) {
19777 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019778 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019779 if (parBind->nodeTable == NULL) {
19780 xmlSchemaVErrMemory(NULL,
19781 "allocating IDC list of node-table items", NULL);
19782 return(-1);
19783 }
19784 parBind->sizeNodes = 1;
19785 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019786 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019787 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19788 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19789 sizeof(xmlSchemaPSVIIDCNodePtr));
19790 if (parBind->nodeTable == NULL) {
19791 xmlSchemaVErrMemory(NULL,
19792 "re-allocating IDC list of node-table items", NULL);
19793 return(-1);
19794 }
19795 }
19796
19797 /*
19798 * Move first old duplicate to last position
19799 * of old duplicates +1.
19800 */
19801 if (parBind->nbDupls != 0) {
19802 parBind->nodeTable[duplTop] =
19803 parBind->nodeTable[parBind->nbNodes + newDupls];
19804 }
19805 /*
19806 * Move first new duplicate to last position of
19807 * new duplicates +1.
19808 */
19809 if (newDupls != 0) {
19810 parBind->nodeTable[parBind->nbNodes + newDupls] =
19811 parBind->nodeTable[parBind->nbNodes];
19812 }
19813 /*
19814 * Append the new node-table entry to the 'new node-table
19815 * entries' section.
19816 */
19817 parBind->nodeTable[parBind->nbNodes] = node;
19818 parBind->nbNodes++;
19819 duplTop++;
19820 }
19821 }
19822 parBind->nbDupls += newDupls;
19823 break;
19824 }
19825 if (parBind->next == NULL)
19826 lastParBind = parBind;
19827 parBind = parBind->next;
19828 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019829 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019830 /*
19831 * No binding for the IDC was found: create a new one and
19832 * copy all node-tables.
19833 */
19834 parBind = xmlSchemaIDCNewBinding(bind->definition);
19835 if (parBind == NULL)
19836 return(-1);
19837
19838 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19839 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19840 if (parBind->nodeTable == NULL) {
19841 xmlSchemaVErrMemory(NULL,
19842 "allocating an array of IDC node-table items", NULL);
19843 xmlSchemaIDCFreeBinding(parBind);
19844 return(-1);
19845 }
19846 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019847 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019848 memcpy(parBind->nodeTable, bind->nodeTable,
19849 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019850 if (*parTable == NULL)
19851 *parTable = parBind;
19852 else
19853 lastParBind->next = parBind;
19854 }
19855 bind = bind->next;
19856 }
19857 return (0);
19858}
19859
19860/**
19861 * xmlSchemaCheckCVCIDCKeyRef:
19862 * @vctxt: the WXS validation context
19863 * @elemDecl: the element declaration
19864 *
19865 * Check the cvc-idc-keyref constraints.
19866 */
19867static int
19868xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19869{
19870 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19871
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019872 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019873 /*
19874 * Find a keyref.
19875 */
19876 while (refbind != NULL) {
19877 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19878 int i, j, k, res;
19879 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19880 xmlSchemaPSVIIDCKeyPtr refKey, key;
19881
19882 /*
19883 * Find the referred key/unique.
19884 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019885 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019886 do {
19887 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19888 bind->definition)
19889 break;
19890 bind = bind->next;
19891 } while (bind != NULL);
19892
19893 /*
19894 * Search for a matching key-sequences.
19895 */
19896 for (i = 0; i < refbind->nbNodes; i++) {
19897 res = 0;
19898 if (bind != NULL) {
19899 refKeys = refbind->nodeTable[i]->keys;
19900 for (j = 0; j < bind->nbNodes; j++) {
19901 keys = bind->nodeTable[j]->keys;
19902 for (k = 0; k < bind->definition->nbFields; k++) {
19903 refKey = refKeys[k];
19904 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019905 res = xmlSchemaAreValuesEqual(key->val,
19906 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019907 if (res == 0)
19908 break;
19909 else if (res == -1) {
19910 return (-1);
19911 }
19912 }
19913 if (res == 1) {
19914 /*
19915 * Match found.
19916 */
19917 break;
19918 }
19919 }
19920 }
19921 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019922 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019923 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019924 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19925 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019926 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019927 "No match found for key-sequence %s of key "
19928 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019929 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019930 refbind->nodeTable[i]->keys,
19931 refbind->definition->nbFields),
19932 xmlSchemaFormatQName(&strB,
19933 refbind->definition->targetNamespace,
19934 refbind->definition->name));
19935 FREE_AND_NULL(str);
19936 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019937 }
19938 }
19939 }
19940 refbind = refbind->next;
19941 }
19942 return (0);
19943}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019944
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019945/************************************************************************
19946 * *
19947 * XML Reader validation code *
19948 * *
19949 ************************************************************************/
19950
19951static xmlSchemaAttrInfoPtr
19952xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019953{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019954 xmlSchemaAttrInfoPtr iattr;
19955 /*
19956 * Grow/create list of attribute infos.
19957 */
19958 if (vctxt->attrInfos == NULL) {
19959 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19960 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
19961 vctxt->sizeAttrInfos = 1;
19962 if (vctxt->attrInfos == NULL) {
19963 xmlSchemaVErrMemory(vctxt,
19964 "allocating attribute info list", NULL);
19965 return (NULL);
19966 }
19967 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
19968 vctxt->sizeAttrInfos++;
19969 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
19970 xmlRealloc(vctxt->attrInfos,
19971 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
19972 if (vctxt->attrInfos == NULL) {
19973 xmlSchemaVErrMemory(vctxt,
19974 "re-allocating attribute info list", NULL);
19975 return (NULL);
19976 }
19977 } else {
19978 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
19979 if (iattr->localName != NULL) {
19980 VERROR_INT("xmlSchemaGetFreshAttrInfo",
19981 "attr info not cleared");
19982 return (NULL);
19983 }
19984 iattr->nodeType = XML_ATTRIBUTE_NODE;
19985 return (iattr);
19986 }
19987 /*
19988 * Create an attribute info.
19989 */
19990 iattr = (xmlSchemaAttrInfoPtr)
19991 xmlMalloc(sizeof(xmlSchemaAttrInfo));
19992 if (iattr == NULL) {
19993 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
19994 return (NULL);
19995 }
19996 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
19997 iattr->nodeType = XML_ATTRIBUTE_NODE;
19998 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
19999
20000 return (iattr);
20001}
20002
20003static int
20004xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20005 xmlNodePtr attrNode,
20006 const xmlChar *localName,
20007 const xmlChar *nsName,
20008 int ownedNames,
20009 xmlChar *value,
20010 int ownedValue)
20011{
20012 xmlSchemaAttrInfoPtr attr;
20013
20014 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20015 if (attr == NULL) {
20016 VERROR_INT("xmlSchemaPushAttribute",
20017 "calling xmlSchemaGetFreshAttrInfo()");
20018 return (-1);
20019 }
20020 attr->node = attrNode;
20021 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20022 attr->localName = localName;
20023 attr->nsName = nsName;
20024 if (ownedNames)
20025 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20026 /*
20027 * Evaluate if it's an XSI attribute.
20028 */
20029 if (nsName != NULL) {
20030 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20031 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20032 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20033 }
20034 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20035 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20036 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20037 }
20038 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20039 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20040 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20041 }
20042 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20043 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20044 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20045 }
20046 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20047 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20048 }
20049 }
20050 attr->value = value;
20051 if (ownedValue)
20052 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20053 if (attr->metaType != 0)
20054 attr->state = XML_SCHEMAS_ATTR_META;
20055 return (0);
20056}
20057
20058static void
20059xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20060{
20061 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20062 FREE_AND_NULL(ielem->localName);
20063 FREE_AND_NULL(ielem->nsName);
20064 } else {
20065 ielem->localName = NULL;
20066 ielem->nsName = NULL;
20067 }
20068 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20069 FREE_AND_NULL(ielem->value);
20070 } else {
20071 ielem->value = NULL;
20072 }
20073 if (ielem->val != NULL) {
20074 xmlSchemaFreeValue(ielem->val);
20075 ielem->val = NULL;
20076 }
20077 if (ielem->idcMatchers != NULL) {
20078 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20079 ielem->idcMatchers = NULL;
20080 }
20081 if (ielem->idcTable != NULL) {
20082 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20083 ielem->idcTable = NULL;
20084 }
20085 if (ielem->regexCtxt != NULL) {
20086 xmlRegFreeExecCtxt(ielem->regexCtxt);
20087 ielem->regexCtxt = NULL;
20088 }
20089 if (ielem->nsBindings != NULL) {
20090 xmlFree((xmlChar **)ielem->nsBindings);
20091 ielem->nsBindings = NULL;
20092 ielem->nbNsBindings = 0;
20093 ielem->sizeNsBindings = 0;
20094 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020095}
20096
20097/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020098 * xmlSchemaGetFreshElemInfo:
20099 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020100 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020101 * Creates/reuses and initializes the element info item for
20102 * the currect tree depth.
20103 *
20104 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020105 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020106static xmlSchemaNodeInfoPtr
20107xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020108{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020109 xmlSchemaNodeInfoPtr info = NULL;
20110
20111 if (vctxt->depth > vctxt->sizeElemInfos) {
20112 VERROR_INT("xmlSchemaGetFreshElemInfo",
20113 "inconsistent depth encountered");
20114 return (NULL);
20115 }
20116 if (vctxt->elemInfos == NULL) {
20117 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20118 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20119 if (vctxt->elemInfos == NULL) {
20120 xmlSchemaVErrMemory(vctxt,
20121 "allocating the element info array", NULL);
20122 return (NULL);
20123 }
20124 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20125 vctxt->sizeElemInfos = 10;
20126 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20127 int i = vctxt->sizeElemInfos;
20128
20129 vctxt->sizeElemInfos *= 2;
20130 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20131 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20132 sizeof(xmlSchemaNodeInfoPtr));
20133 if (vctxt->elemInfos == NULL) {
20134 xmlSchemaVErrMemory(vctxt,
20135 "re-allocating the element info array", NULL);
20136 return (NULL);
20137 }
20138 /*
20139 * We need the new memory to be NULLed.
20140 * TODO: Use memset instead?
20141 */
20142 for (; i < vctxt->sizeElemInfos; i++)
20143 vctxt->elemInfos[i] = NULL;
20144 } else
20145 info = vctxt->elemInfos[vctxt->depth];
20146
20147 if (info == NULL) {
20148 info = (xmlSchemaNodeInfoPtr)
20149 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20150 if (info == NULL) {
20151 xmlSchemaVErrMemory(vctxt,
20152 "allocating an element info", NULL);
20153 return (NULL);
20154 }
20155 vctxt->elemInfos[vctxt->depth] = info;
20156 } else {
20157 if (info->localName != NULL) {
20158 VERROR_INT("xmlSchemaGetFreshElemInfo",
20159 "elem info has not been cleared");
20160 return (NULL);
20161 }
20162 }
20163 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20164 info->nodeType = XML_ELEMENT_NODE;
20165 info->depth = vctxt->depth;
20166
20167 return (info);
20168}
20169
20170#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20171#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20172#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20173
20174static int
20175xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20176 xmlNodePtr node,
20177 xmlSchemaTypePtr type,
20178 xmlSchemaValType valType,
20179 const xmlChar * value,
20180 xmlSchemaValPtr val,
20181 unsigned long length,
20182 int fireErrors)
20183{
20184 int ret, error = 0;
20185
20186 xmlSchemaTypePtr tmpType;
20187 xmlSchemaFacetLinkPtr facetLink;
20188 xmlSchemaFacetPtr facet;
20189 unsigned long len = 0;
20190 xmlSchemaWhitespaceValueType ws;
20191
20192 /*
20193 * In Libxml2, derived built-in types have currently no explicit facets.
20194 */
20195 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020196 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020197
20198 /*
20199 * NOTE: Do not jump away, if the facetSet of the given type is
20200 * empty: until now, "pattern" and "enumeration" facets of the
20201 * *base types* need to be checked as well.
20202 */
20203 if (type->facetSet == NULL)
20204 goto pattern_and_enum;
20205
20206 if (! VARIETY_ATOMIC(type)) {
20207 if (VARIETY_LIST(type))
20208 goto variety_list;
20209 else
20210 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020211 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020212 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020213 * Whitespace handling is only of importance for string-based
20214 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020215 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020216 tmpType = xmlSchemaGetPrimitiveType(type);
20217 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20218 IS_ANY_SIMPLE_TYPE(tmpType)) {
20219 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20220 } else
20221 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20222 /*
20223 * If the value was not computed (for string or
20224 * anySimpleType based types), then use the provided
20225 * type.
20226 */
20227 if (val == NULL)
20228 valType = valType;
20229 else
20230 valType = xmlSchemaGetValType(val);
20231
20232 ret = 0;
20233 for (facetLink = type->facetSet; facetLink != NULL;
20234 facetLink = facetLink->next) {
20235 /*
20236 * Skip the pattern "whiteSpace": it is used to
20237 * format the character content beforehand.
20238 */
20239 switch (facetLink->facet->type) {
20240 case XML_SCHEMA_FACET_WHITESPACE:
20241 case XML_SCHEMA_FACET_PATTERN:
20242 case XML_SCHEMA_FACET_ENUMERATION:
20243 continue;
20244 case XML_SCHEMA_FACET_LENGTH:
20245 case XML_SCHEMA_FACET_MINLENGTH:
20246 case XML_SCHEMA_FACET_MAXLENGTH:
20247 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20248 valType, value, val, &len, ws);
20249 break;
20250 default:
20251 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20252 valType, value, val, ws);
20253 break;
20254 }
20255 if (ret < 0) {
20256 AERROR_INT("xmlSchemaValidateFacets",
20257 "validating against a atomic type facet");
20258 return (-1);
20259 } else if (ret > 0) {
20260 if (fireErrors)
20261 xmlSchemaFacetErr(actxt, ret, node,
20262 value, len, type, facetLink->facet, NULL, NULL, NULL);
20263 else
20264 return (ret);
20265 if (error == 0)
20266 error = ret;
20267 }
20268 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020269 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020270
20271variety_list:
20272 if (! VARIETY_LIST(type))
20273 goto pattern_and_enum;
20274 /*
20275 * "length", "minLength" and "maxLength" of list types.
20276 */
20277 ret = 0;
20278 for (facetLink = type->facetSet; facetLink != NULL;
20279 facetLink = facetLink->next) {
20280
20281 switch (facetLink->facet->type) {
20282 case XML_SCHEMA_FACET_LENGTH:
20283 case XML_SCHEMA_FACET_MINLENGTH:
20284 case XML_SCHEMA_FACET_MAXLENGTH:
20285 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20286 value, length, NULL);
20287 break;
20288 default:
20289 continue;
20290 }
20291 if (ret < 0) {
20292 AERROR_INT("xmlSchemaValidateFacets",
20293 "validating against a list type facet");
20294 return (-1);
20295 } else if (ret > 0) {
20296 if (fireErrors)
20297 xmlSchemaFacetErr(actxt, ret, node,
20298 value, length, type, facetLink->facet, NULL, NULL, NULL);
20299 else
20300 return (ret);
20301 if (error == 0)
20302 error = ret;
20303 }
20304 ret = 0;
20305 }
20306
20307pattern_and_enum:
20308 if (error >= 0) {
20309 int found = 0;
20310 /*
20311 * Process enumerations. Facet values are in the value space
20312 * of the defining type's base type. This seems to be a bug in the
20313 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20314 * Only the first set of enumerations in the ancestor-or-self axis
20315 * is used for validation.
20316 */
20317 ret = 0;
20318 tmpType = type;
20319 do {
20320 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20321 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20322 continue;
20323 found = 1;
20324 ret = xmlSchemaAreValuesEqual(facet->val, val);
20325 if (ret == 1)
20326 break;
20327 else if (ret < 0) {
20328 AERROR_INT("xmlSchemaValidateFacets",
20329 "validating against an enumeration facet");
20330 return (-1);
20331 }
20332 }
20333 if (ret != 0)
20334 break;
20335 tmpType = tmpType->baseType;
20336 } while ((tmpType != NULL) &&
20337 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20338 if (found && (ret == 0)) {
20339 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20340 if (fireErrors) {
20341 xmlSchemaFacetErr(actxt, ret, node,
20342 value, 0, type, NULL, NULL, NULL, NULL);
20343 } else
20344 return (ret);
20345 if (error == 0)
20346 error = ret;
20347 }
20348 }
20349
20350 if (error >= 0) {
20351 int found;
20352 /*
20353 * Process patters. Pattern facets are ORed at type level
20354 * and ANDed if derived. Walk the base type axis.
20355 */
20356 tmpType = type;
20357 facet = NULL;
20358 do {
20359 found = 0;
20360 for (facetLink = tmpType->facetSet; facetLink != NULL;
20361 facetLink = facetLink->next) {
20362 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20363 continue;
20364 found = 1;
20365 /*
20366 * NOTE that for patterns, @value needs to be the
20367 * normalized vaule.
20368 */
20369 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20370 if (ret == 1)
20371 break;
20372 else if (ret < 0) {
20373 AERROR_INT("xmlSchemaValidateFacets",
20374 "validating against a pattern facet");
20375 return (-1);
20376 } else {
20377 /*
20378 * Save the last non-validating facet.
20379 */
20380 facet = facetLink->facet;
20381 }
20382 }
20383 if (found && (ret != 1)) {
20384 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20385 if (fireErrors) {
20386 xmlSchemaFacetErr(actxt, ret, node,
20387 value, 0, type, facet, NULL, NULL, NULL);
20388 } else
20389 return (ret);
20390 if (error == 0)
20391 error = ret;
20392 break;
20393 }
20394 tmpType = tmpType->baseType;
20395 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20396 }
20397
20398 return (error);
20399}
20400
20401static xmlChar *
20402xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20403 const xmlChar *value)
20404{
20405 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20406 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20407 return (xmlSchemaCollapseString(value));
20408 case XML_SCHEMA_WHITESPACE_REPLACE:
20409 return (xmlSchemaWhiteSpaceReplace(value));
20410 default:
20411 return (NULL);
20412 }
20413}
20414
20415static int
20416xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20417 const xmlChar *value,
20418 xmlSchemaValPtr *val,
20419 int valNeeded)
20420{
20421 int ret;
20422 const xmlChar *nsName;
20423 xmlChar *local, *prefix = NULL;
20424
20425 ret = xmlValidateQName(value, 1);
20426 if (ret != 0) {
20427 if (ret == -1) {
20428 VERROR_INT("xmlSchemaValidateQName",
20429 "calling xmlValidateQName()");
20430 return (-1);
20431 }
20432 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20433 }
20434 /*
20435 * NOTE: xmlSplitQName2 will always return a duplicated
20436 * strings.
20437 */
20438 local = xmlSplitQName2(value, &prefix);
20439 if (local == NULL)
20440 local = xmlStrdup(value);
20441 /*
20442 * OPTIMIZE TODO: Use flags for:
20443 * - is there any namespace binding?
20444 * - is there a default namespace?
20445 */
20446 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20447
20448 if (prefix != NULL) {
20449 xmlFree(prefix);
20450 /*
20451 * A namespace must be found if the prefix is
20452 * NOT NULL.
20453 */
20454 if (nsName == NULL) {
20455 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20456 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20457 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20458 "The QName value '%s' has no "
20459 "corresponding namespace declaration in "
20460 "scope", value, NULL);
20461 if (local != NULL)
20462 xmlFree(local);
20463 return (ret);
20464 }
20465 }
20466 if (valNeeded && val) {
20467 if (nsName != NULL)
20468 *val = xmlSchemaNewQNameValue(
20469 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20470 else
20471 *val = xmlSchemaNewQNameValue(NULL,
20472 BAD_CAST local);
20473 } else
20474 xmlFree(local);
20475 return (0);
20476}
20477
20478/*
20479* cvc-simple-type
20480*/
20481static int
20482xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20483 xmlNodePtr node,
20484 xmlSchemaTypePtr type,
20485 const xmlChar *value,
20486 xmlSchemaValPtr *retVal,
20487 int fireErrors,
20488 int normalize,
20489 int isNormalized)
20490{
20491 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20492 xmlSchemaValPtr val = NULL;
20493 xmlSchemaWhitespaceValueType ws;
20494 xmlChar *normValue = NULL;
20495
20496#define NORMALIZE(atype) \
20497 if ((! isNormalized) && \
20498 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20499 normValue = xmlSchemaNormalizeValue(atype, value); \
20500 if (normValue != NULL) \
20501 value = normValue; \
20502 isNormalized = 1; \
20503 }
20504
20505 if ((retVal != NULL) && (*retVal != NULL)) {
20506 xmlSchemaFreeValue(*retVal);
20507 *retVal = NULL;
20508 }
20509 /*
20510 * 3.14.4 Simple Type Definition Validation Rules
20511 * Validation Rule: String Valid
20512 */
20513 /*
20514 * 1 It is schema-valid with respect to that definition as defined
20515 * by Datatype Valid in [XML Schemas: Datatypes].
20516 */
20517 /*
20518 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20519 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20520 * the string must be a ·declared entity name·.
20521 */
20522 /*
20523 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20524 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20525 * then every whitespace-delimited substring of the string must be a ·declared
20526 * entity name·.
20527 */
20528 /*
20529 * 2.3 otherwise no further condition applies.
20530 */
20531 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20532 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020533 if (value == NULL)
20534 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020535 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20536 xmlSchemaTypePtr biType; /* The built-in type. */
20537 /*
20538 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20539 * a literal in the ·lexical space· of {base type definition}"
20540 */
20541 /*
20542 * Whitespace-normalize.
20543 */
20544 NORMALIZE(type);
20545 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20546 /*
20547 * Get the built-in type.
20548 */
20549 biType = type->baseType;
20550 while ((biType != NULL) &&
20551 (biType->type != XML_SCHEMA_TYPE_BASIC))
20552 biType = biType->baseType;
20553
20554 if (biType == NULL) {
20555 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20556 "could not get the built-in type");
20557 goto internal_error;
20558 }
20559 } else
20560 biType = type;
20561 /*
20562 * NOTATIONs need to be processed here, since they need
20563 * to lookup in the hashtable of NOTATION declarations of the schema.
20564 */
20565 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20566 switch (biType->builtInType) {
20567 case XML_SCHEMAS_NOTATION:
20568 ret = xmlSchemaValidateNotation(
20569 (xmlSchemaValidCtxtPtr) actxt,
20570 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20571 NULL, value, &val, valNeeded);
20572 break;
20573 case XML_SCHEMAS_QNAME:
20574 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20575 value, &val, valNeeded);
20576 break;
20577 default:
20578 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20579 if (valNeeded)
20580 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20581 value, &val, NULL);
20582 else
20583 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20584 value, NULL, NULL);
20585 break;
20586 }
20587 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20588 switch (biType->builtInType) {
20589 case XML_SCHEMAS_NOTATION:
20590 ret = xmlSchemaValidateNotation(NULL,
20591 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20592 value, &val, valNeeded);
20593 break;
20594 default:
20595 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20596 if (valNeeded)
20597 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20598 value, &val, node);
20599 else
20600 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20601 value, NULL, node);
20602 break;
20603 }
20604 } else {
20605 /*
20606 * Validation via a public API is not implemented yet.
20607 */
20608 TODO
20609 goto internal_error;
20610 }
20611 if (ret != 0) {
20612 if (ret < 0) {
20613 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20614 "validating against a built-in type");
20615 goto internal_error;
20616 }
20617 if (VARIETY_LIST(type))
20618 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20619 else
20620 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20621 }
20622 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20623 /*
20624 * Check facets.
20625 */
20626 ret = xmlSchemaValidateFacets(actxt, node, type,
20627 (xmlSchemaValType) biType->builtInType, value, val,
20628 0, fireErrors);
20629 if (ret != 0) {
20630 if (ret < 0) {
20631 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20632 "validating facets of atomic simple type");
20633 goto internal_error;
20634 }
20635 if (VARIETY_LIST(type))
20636 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20637 else
20638 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20639 }
20640 }
20641 if (fireErrors && (ret > 0))
20642 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20643 } else if (VARIETY_LIST(type)) {
20644
20645 xmlSchemaTypePtr itemType;
20646 const xmlChar *cur, *end;
20647 xmlChar *tmpValue = NULL;
20648 unsigned long len = 0;
20649 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20650 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20651 * of white space separated tokens, each of which ·match·es a literal
20652 * in the ·lexical space· of {item type definition}
20653 */
20654 /*
20655 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20656 * the list type has an enum or pattern facet.
20657 */
20658 NORMALIZE(type);
20659 /*
20660 * VAL TODO: Optimize validation of empty values.
20661 * VAL TODO: We do not have computed values for lists.
20662 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020663 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020664 cur = value;
20665 do {
20666 while (IS_BLANK_CH(*cur))
20667 cur++;
20668 end = cur;
20669 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20670 end++;
20671 if (end == cur)
20672 break;
20673 tmpValue = xmlStrndup(cur, end - cur);
20674 len++;
20675
20676 if (valNeeded)
20677 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20678 tmpValue, &curVal, fireErrors, 0, 1);
20679 else
20680 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20681 tmpValue, NULL, fireErrors, 0, 1);
20682 FREE_AND_NULL(tmpValue);
20683 if (curVal != NULL) {
20684 /*
20685 * Add to list of computed values.
20686 */
20687 if (val == NULL)
20688 val = curVal;
20689 else
20690 xmlSchemaValueAppend(prevVal, curVal);
20691 prevVal = curVal;
20692 curVal = NULL;
20693 }
20694 if (ret != 0) {
20695 if (ret < 0) {
20696 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20697 "validating an item of list simple type");
20698 goto internal_error;
20699 }
20700 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20701 break;
20702 }
20703 cur = end;
20704 } while (*cur != 0);
20705 FREE_AND_NULL(tmpValue);
20706 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20707 /*
20708 * Apply facets (pattern, enumeration).
20709 */
20710 ret = xmlSchemaValidateFacets(actxt, node, type,
20711 XML_SCHEMAS_UNKNOWN, value, val,
20712 len, fireErrors);
20713 if (ret != 0) {
20714 if (ret < 0) {
20715 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20716 "validating facets of list simple type");
20717 goto internal_error;
20718 }
20719 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20720 }
20721 }
20722 if (fireErrors && (ret > 0)) {
20723 /*
20724 * Report the normalized value.
20725 */
20726 normalize = 1;
20727 NORMALIZE(type);
20728 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20729 }
20730 } else if (VARIETY_UNION(type)) {
20731 xmlSchemaTypeLinkPtr memberLink;
20732 /*
20733 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20734 * not apply directly; however, the normalization behavior of ·union·
20735 * types is controlled by the value of whiteSpace on that one of the
20736 * ·memberTypes· against which the ·union· is successfully validated.
20737 *
20738 * This means that the value is normalized by the first validating
20739 * member type, then the facets of the union type are applied. This
20740 * needs changing of the value!
20741 */
20742
20743 /*
20744 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20745 * literal in the ·lexical space· of at least one member of
20746 * {member type definitions}
20747 */
20748 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20749 if (memberLink == NULL) {
20750 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20751 "union simple type has no member types");
20752 goto internal_error;
20753 }
20754 /*
20755 * Always normalize union type values, since we currently
20756 * cannot store the whitespace information with the value
20757 * itself; otherwise a later value-comparison would be
20758 * not possible.
20759 */
20760 while (memberLink != NULL) {
20761 if (valNeeded)
20762 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20763 memberLink->type, value, &val, 0, 1, 0);
20764 else
20765 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20766 memberLink->type, value, NULL, 0, 1, 0);
20767 if (ret <= 0)
20768 break;
20769 memberLink = memberLink->next;
20770 }
20771 if (ret != 0) {
20772 if (ret < 0) {
20773 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20774 "validating members of union simple type");
20775 goto internal_error;
20776 }
20777 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20778 }
20779 /*
20780 * Apply facets (pattern, enumeration).
20781 */
20782 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20783 /*
20784 * The normalization behavior of ·union· types is controlled by
20785 * the value of whiteSpace on that one of the ·memberTypes·
20786 * against which the ·union· is successfully validated.
20787 */
20788 NORMALIZE(memberLink->type);
20789 ret = xmlSchemaValidateFacets(actxt, node, type,
20790 XML_SCHEMAS_UNKNOWN, value, val,
20791 0, fireErrors);
20792 if (ret != 0) {
20793 if (ret < 0) {
20794 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20795 "validating facets of union simple type");
20796 goto internal_error;
20797 }
20798 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20799 }
20800 }
20801 if (fireErrors && (ret > 0))
20802 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20803 }
20804
20805 if (normValue != NULL)
20806 xmlFree(normValue);
20807 if (ret == 0) {
20808 if (retVal != NULL)
20809 *retVal = val;
20810 else if (val != NULL)
20811 xmlSchemaFreeValue(val);
20812 } else if (val != NULL)
20813 xmlSchemaFreeValue(val);
20814 return (ret);
20815internal_error:
20816 if (normValue != NULL)
20817 xmlFree(normValue);
20818 if (val != NULL)
20819 xmlSchemaFreeValue(val);
20820 return (-1);
20821}
20822
20823static int
20824xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20825 const xmlChar *value,
20826 const xmlChar **nsName,
20827 const xmlChar **localName)
20828{
20829 int ret = 0;
20830
20831 if ((nsName == NULL) || (localName == NULL))
20832 return (-1);
20833 *nsName = NULL;
20834 *localName = NULL;
20835
20836 ret = xmlValidateQName(value, 1);
20837 if (ret == -1)
20838 return (-1);
20839 if (ret > 0) {
20840 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20841 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20842 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20843 return (1);
20844 }
20845 {
20846 xmlChar *local = NULL;
20847 xmlChar *prefix;
20848
20849 /*
20850 * NOTE: xmlSplitQName2 will return a duplicated
20851 * string.
20852 */
20853 local = xmlSplitQName2(value, &prefix);
20854 VAL_CREATE_DICT;
20855 if (local == NULL)
20856 *localName = xmlDictLookup(vctxt->dict, value, -1);
20857 else {
20858 *localName = xmlDictLookup(vctxt->dict, local, -1);
20859 xmlFree(local);
20860 }
20861
20862 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20863
20864 if (prefix != NULL) {
20865 xmlFree(prefix);
20866 /*
20867 * A namespace must be found if the prefix is NOT NULL.
20868 */
20869 if (*nsName == NULL) {
20870 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20871 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20872 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20873 "The QName value '%s' has no "
20874 "corresponding namespace declaration in scope",
20875 value, NULL);
20876 return (2);
20877 }
20878 }
20879 }
20880 return (0);
20881}
20882
20883static int
20884xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20885 xmlSchemaAttrInfoPtr iattr,
20886 xmlSchemaTypePtr *localType,
20887 xmlSchemaElementPtr elemDecl)
20888{
20889 int ret = 0;
20890 /*
20891 * cvc-elt (3.3.4) : (4)
20892 * AND
20893 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20894 * (1.2.1.2.1) - (1.2.1.2.4)
20895 * Handle 'xsi:type'.
20896 */
20897 if (localType == NULL)
20898 return (-1);
20899 *localType = NULL;
20900 if (iattr == NULL)
20901 return (0);
20902 else {
20903 const xmlChar *nsName = NULL, *local = NULL;
20904 /*
20905 * TODO: We should report a *warning* that the type was overriden
20906 * by the instance.
20907 */
20908 ACTIVATE_ATTRIBUTE(iattr);
20909 /*
20910 * (cvc-elt) (3.3.4) : (4.1)
20911 * (cvc-assess-elt) (1.2.1.2.2)
20912 */
20913 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20914 &nsName, &local);
20915 if (ret != 0) {
20916 if (ret < 0) {
20917 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20918 "calling xmlSchemaQNameExpand() to validate the "
20919 "attribute 'xsi:type'");
20920 goto internal_error;
20921 }
20922 goto exit;
20923 }
20924 /*
20925 * (cvc-elt) (3.3.4) : (4.2)
20926 * (cvc-assess-elt) (1.2.1.2.3)
20927 */
20928 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20929 if (*localType == NULL) {
20930 xmlChar *str = NULL;
20931
20932 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20933 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20934 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20935 "The QName value '%s' of the xsi:type attribute does not "
20936 "resolve to a type definition",
20937 xmlSchemaFormatQName(&str, nsName, local), NULL);
20938 FREE_AND_NULL(str);
20939 ret = vctxt->err;
20940 goto exit;
20941 }
20942 if (elemDecl != NULL) {
20943 int set = 0;
20944
20945 /*
20946 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
20947 * "The ·local type definition· must be validly
20948 * derived from the {type definition} given the union of
20949 * the {disallowed substitutions} and the {type definition}'s
20950 * {prohibited substitutions}, as defined in
20951 * Type Derivation OK (Complex) (§3.4.6)
20952 * (if it is a complex type definition),
20953 * or given {disallowed substitutions} as defined in Type
20954 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
20955 * definition)."
20956 *
20957 * {disallowed substitutions}: the "block" on the element decl.
20958 * {prohibited substitutions}: the "block" on the type def.
20959 */
20960 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
20961 (elemDecl->subtypes->flags &
20962 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
20963 set |= SUBSET_EXTENSION;
20964
20965 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
20966 (elemDecl->subtypes->flags &
20967 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
20968 set |= SUBSET_RESTRICTION;
20969
20970 if (xmlSchemaCheckCOSDerivedOK(*localType,
20971 elemDecl->subtypes, set) != 0) {
20972 xmlChar *str = NULL;
20973
20974 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20975 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
20976 "The type definition '%s', specified by xsi:type, is "
20977 "blocked or not validly derived from the type definition "
20978 "of the element declaration",
20979 xmlSchemaFormatQName(&str,
20980 (*localType)->targetNamespace,
20981 (*localType)->name),
20982 NULL);
20983 FREE_AND_NULL(str);
20984 ret = vctxt->err;
20985 *localType = NULL;
20986 }
20987 }
20988 }
20989exit:
20990 ACTIVATE_ELEM;
20991 return (ret);
20992internal_error:
20993 ACTIVATE_ELEM;
20994 return (-1);
20995}
20996
20997static int
20998xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
20999{
21000 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21001 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21002
21003 /*
21004 * cvc-elt (3.3.4) : 1
21005 */
21006 if (elemDecl == NULL) {
21007 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21008 "No matching declaration available");
21009 return (vctxt->err);
21010 }
21011 /*
21012 * cvc-elt (3.3.4) : 2
21013 */
21014 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21015 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21016 "The element declaration is abstract");
21017 return (vctxt->err);
21018 }
21019 if (actualType == NULL) {
21020 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21021 "The type definition is absent");
21022 return (XML_SCHEMAV_CVC_TYPE_1);
21023 }
21024 if (vctxt->nbAttrInfos != 0) {
21025 int ret;
21026 xmlSchemaAttrInfoPtr iattr;
21027 /*
21028 * cvc-elt (3.3.4) : 3
21029 * Handle 'xsi:nil'.
21030 */
21031 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21032 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21033 if (iattr) {
21034 ACTIVATE_ATTRIBUTE(iattr);
21035 /*
21036 * Validate the value.
21037 */
21038 ret = xmlSchemaVCheckCVCSimpleType(
21039 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21040 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21041 iattr->value, &(iattr->val), 1, 0, 0);
21042 ACTIVATE_ELEM;
21043 if (ret < 0) {
21044 VERROR_INT("xmlSchemaValidateElemDecl",
21045 "calling xmlSchemaVCheckCVCSimpleType() to "
21046 "validate the attribute 'xsi:nil'");
21047 return (-1);
21048 }
21049 if (ret == 0) {
21050 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21051 /*
21052 * cvc-elt (3.3.4) : 3.1
21053 */
21054 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21055 "The element is not 'nillable'");
21056 /* Does not return an error on purpose. */
21057 } else {
21058 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21059 /*
21060 * cvc-elt (3.3.4) : 3.2.2
21061 */
21062 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21063 (elemDecl->value != NULL)) {
21064 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21065 "The element cannot be 'nilled' because "
21066 "there is a fixed value constraint defined "
21067 "for it");
21068 /* Does not return an error on purpose. */
21069 } else
21070 vctxt->inode->flags |=
21071 XML_SCHEMA_ELEM_INFO_NILLED;
21072 }
21073 }
21074 }
21075 }
21076 /*
21077 * cvc-elt (3.3.4) : 4
21078 * Handle 'xsi:type'.
21079 */
21080 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21081 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21082 if (iattr) {
21083 xmlSchemaTypePtr localType = NULL;
21084
21085 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21086 elemDecl);
21087 if (ret != 0) {
21088 if (ret == -1) {
21089 VERROR_INT("xmlSchemaValidateElemDecl",
21090 "calling xmlSchemaProcessXSIType() to "
21091 "process the attribute 'xsi:type'");
21092 return (-1);
21093 }
21094 /* Does not return an error on purpose. */
21095 }
21096 if (localType != NULL) {
21097 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21098 actualType = localType;
21099 }
21100 }
21101 }
21102 /*
21103 * IDC: Register identity-constraint XPath matchers.
21104 */
21105 if ((elemDecl->idcs != NULL) &&
21106 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21107 return (-1);
21108 /*
21109 * No actual type definition.
21110 */
21111 if (actualType == NULL) {
21112 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21113 "The type definition is absent");
21114 return (XML_SCHEMAV_CVC_TYPE_1);
21115 }
21116 /*
21117 * Remember the actual type definition.
21118 */
21119 vctxt->inode->typeDef = actualType;
21120
21121 return (0);
21122}
21123
21124static int
21125xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21126{
21127 xmlSchemaAttrInfoPtr iattr;
21128 int ret = 0, i;
21129
21130 /*
21131 * SPEC cvc-type (3.1.1)
21132 * "The attributes of must be empty, excepting those whose namespace
21133 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21134 * whose local name is one of type, nil, schemaLocation or
21135 * noNamespaceSchemaLocation."
21136 */
21137 if (vctxt->nbAttrInfos == 0)
21138 return (0);
21139 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21140 iattr = vctxt->attrInfos[i];
21141 if (! iattr->metaType) {
21142 ACTIVATE_ATTRIBUTE(iattr)
21143 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21144 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21145 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21146 }
21147 }
21148 ACTIVATE_ELEM
21149 return (ret);
21150}
21151
21152/*
21153* Cleanup currently used attribute infos.
21154*/
21155static void
21156xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21157{
21158 int i;
21159 xmlSchemaAttrInfoPtr attr;
21160
21161 if (vctxt->nbAttrInfos == 0)
21162 return;
21163 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21164 attr = vctxt->attrInfos[i];
21165 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21166 if (attr->localName != NULL)
21167 xmlFree((xmlChar *) attr->localName);
21168 if (attr->nsName != NULL)
21169 xmlFree((xmlChar *) attr->nsName);
21170 }
21171 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21172 if (attr->value != NULL)
21173 xmlFree((xmlChar *) attr->value);
21174 }
21175 if (attr->val != NULL) {
21176 xmlSchemaFreeValue(attr->val);
21177 attr->val = NULL;
21178 }
21179 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21180 }
21181 vctxt->nbAttrInfos = 0;
21182}
21183
21184/*
21185* 3.4.4 Complex Type Definition Validation Rules
21186* Element Locally Valid (Complex Type) (cvc-complex-type)
21187* 3.2.4 Attribute Declaration Validation Rules
21188* Validation Rule: Attribute Locally Valid (cvc-attribute)
21189* Attribute Locally Valid (Use) (cvc-au)
21190*
21191* Only "assessed" attribute information items will be visible to
21192* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21193*/
21194static int
21195xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21196{
21197 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21198 xmlSchemaAttributeLinkPtr attrUseLink;
21199 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21200 xmlSchemaAttrInfoPtr attr, tmpAttr;
21201 int i, found, nbAttrs;
21202 int xpathRes = 0, res, wildIDs = 0, fixed;
21203
21204 /*
21205 * SPEC (cvc-attribute)
21206 * (1) "The declaration must not be ·absent· (see Missing
21207 * Sub-components (§5.3) for how this can fail to be
21208 * the case)."
21209 * (2) "Its {type definition} must not be absent."
21210 *
21211 * NOTE (1) + (2): This is not handled here, since we currently do not
21212 * allow validation against schemas which have missing sub-components.
21213 *
21214 * SPEC (cvc-complex-type)
21215 * (3) "For each attribute information item in the element information
21216 * item's [attributes] excepting those whose [namespace name] is
21217 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21218 * [local name] is one of type, nil, schemaLocation or
21219 * noNamespaceSchemaLocation, the appropriate case among the following
21220 * must be true:
21221 *
21222 */
21223 nbAttrs = vctxt->nbAttrInfos;
21224 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21225 attrUseLink = attrUseLink->next) {
21226
21227 found = 0;
21228 attrUse = attrUseLink->attr;
21229 /*
21230 * VAL TODO: Implement a real "attribute use" component.
21231 */
21232 if (attrUse->refDecl != NULL)
21233 attrDecl = attrUse->refDecl;
21234 else
21235 attrDecl = attrUse;
21236 for (i = 0; i < nbAttrs; i++) {
21237 attr = vctxt->attrInfos[i];
21238 /*
21239 * SPEC (cvc-complex-type) (3)
21240 * Skip meta attributes.
21241 */
21242 if (attr->metaType)
21243 continue;
21244 if (attr->localName[0] != attrDecl->name[0])
21245 continue;
21246 if (!xmlStrEqual(attr->localName, attrDecl->name))
21247 continue;
21248 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21249 continue;
21250 found = 1;
21251 /*
21252 * SPEC (cvc-complex-type)
21253 * (3.1) "If there is among the {attribute uses} an attribute
21254 * use with an {attribute declaration} whose {name} matches
21255 * the attribute information item's [local name] and whose
21256 * {target namespace} is identical to the attribute information
21257 * item's [namespace name] (where an ·absent· {target namespace}
21258 * is taken to be identical to a [namespace name] with no value),
21259 * then the attribute information must be ·valid· with respect
21260 * to that attribute use as per Attribute Locally Valid (Use)
21261 * (§3.5.4). In this case the {attribute declaration} of that
21262 * attribute use is the ·context-determined declaration· for the
21263 * attribute information item with respect to Schema-Validity
21264 * Assessment (Attribute) (§3.2.4) and
21265 * Assessment Outcome (Attribute) (§3.2.5).
21266 */
21267 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21268 attr->use = attrUse;
21269 /*
21270 * Context-determined declaration.
21271 */
21272 attr->decl = attrDecl;
21273 attr->typeDef = attrDecl->subtypes;
21274 break;
21275 }
21276
21277 if (found)
21278 continue;
21279
21280 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21281 /*
21282 * Handle non-existent, required attributes.
21283 *
21284 * SPEC (cvc-complex-type)
21285 * (4) "The {attribute declaration} of each attribute use in
21286 * the {attribute uses} whose {required} is true matches one
21287 * of the attribute information items in the element information
21288 * item's [attributes] as per clause 3.1 above."
21289 */
21290 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21291 if (tmpAttr == NULL) {
21292 VERROR_INT(
21293 "xmlSchemaVAttributesComplex",
21294 "calling xmlSchemaGetFreshAttrInfo()");
21295 return (-1);
21296 }
21297 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21298 tmpAttr->use = attrUse;
21299 tmpAttr->decl = attrDecl;
21300 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21301 ((attrUse->defValue != NULL) ||
21302 (attrDecl->defValue != NULL))) {
21303 /*
21304 * Handle non-existent, optional, default/fixed attributes.
21305 */
21306 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21307 if (tmpAttr == NULL) {
21308 VERROR_INT(
21309 "xmlSchemaVAttributesComplex",
21310 "calling xmlSchemaGetFreshAttrInfo()");
21311 return (-1);
21312 }
21313 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21314 tmpAttr->use = attrUse;
21315 tmpAttr->decl = attrDecl;
21316 tmpAttr->typeDef = attrDecl->subtypes;
21317 tmpAttr->localName = attrDecl->name;
21318 tmpAttr->nsName = attrDecl->targetNamespace;
21319 }
21320 }
21321 if (vctxt->nbAttrInfos == 0)
21322 return (0);
21323 /*
21324 * Validate against the wildcard.
21325 */
21326 if (type->attributeWildcard != NULL) {
21327 /*
21328 * SPEC (cvc-complex-type)
21329 * (3.2.1) "There must be an {attribute wildcard}."
21330 */
21331 for (i = 0; i < nbAttrs; i++) {
21332 attr = vctxt->attrInfos[i];
21333 /*
21334 * SPEC (cvc-complex-type) (3)
21335 * Skip meta attributes.
21336 */
21337 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21338 continue;
21339 /*
21340 * SPEC (cvc-complex-type)
21341 * (3.2.2) "The attribute information item must be ·valid· with
21342 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21343 *
21344 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21345 * "... its [namespace name] must be ·valid· with respect to
21346 * the wildcard constraint, as defined in Wildcard allows
21347 * Namespace Name (§3.10.4)."
21348 */
21349 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21350 attr->nsName)) {
21351 /*
21352 * Handle processContents.
21353 *
21354 * SPEC (cvc-wildcard):
21355 * processContents | context-determined declaration:
21356 * "strict" "mustFind"
21357 * "lax" "none"
21358 * "skip" "skip"
21359 */
21360 if (type->attributeWildcard->processContents ==
21361 XML_SCHEMAS_ANY_SKIP) {
21362 /*
21363 * context-determined declaration = "skip"
21364 *
21365 * SPEC PSVI Assessment Outcome (Attribute)
21366 * [validity] = "notKnown"
21367 * [validation attempted] = "none"
21368 */
21369 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21370 continue;
21371 }
21372 /*
21373 * Find an attribute declaration.
21374 */
21375 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21376 attr->localName, attr->nsName);
21377 if (attr->decl != NULL) {
21378 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21379 /*
21380 * SPEC (cvc-complex-type)
21381 * (5) "Let [Definition:] the wild IDs be the set of
21382 * all attribute information item to which clause 3.2
21383 * applied and whose ·validation· resulted in a
21384 * ·context-determined declaration· of mustFind or no
21385 * ·context-determined declaration· at all, and whose
21386 * [local name] and [namespace name] resolve (as
21387 * defined by QName resolution (Instance) (§3.15.4)) to
21388 * an attribute declaration whose {type definition} is
21389 * or is derived from ID. Then all of the following
21390 * must be true:"
21391 */
21392 attr->typeDef = attr->decl->subtypes;
21393 if (xmlSchemaIsDerivedFromBuiltInType(
21394 attr->typeDef, XML_SCHEMAS_ID)) {
21395 /*
21396 * SPEC (5.1) "There must be no more than one
21397 * item in ·wild IDs·."
21398 */
21399 if (wildIDs != 0) {
21400 /* VAL TODO */
21401 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21402 TODO
21403 continue;
21404 }
21405 wildIDs++;
21406 /*
21407 * SPEC (cvc-complex-type)
21408 * (5.2) "If ·wild IDs· is non-empty, there must not
21409 * be any attribute uses among the {attribute uses}
21410 * whose {attribute declaration}'s {type definition}
21411 * is or is derived from ID."
21412 */
21413 for (attrUseLink = type->attributeUses;
21414 attrUseLink != NULL;
21415 attrUseLink = attrUseLink->next) {
21416 if (xmlSchemaIsDerivedFromBuiltInType(
21417 attrUseLink->attr->subtypes,
21418 XML_SCHEMAS_ID)) {
21419 /* VAL TODO */
21420 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21421 TODO
21422 }
21423 }
21424 }
21425 } else if (type->attributeWildcard->processContents ==
21426 XML_SCHEMAS_ANY_LAX) {
21427 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21428 /*
21429 * SPEC PSVI Assessment Outcome (Attribute)
21430 * [validity] = "notKnown"
21431 * [validation attempted] = "none"
21432 */
21433 } else {
21434 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21435 }
21436 }
21437 }
21438 }
21439
21440
21441 if (vctxt->nbAttrInfos == 0)
21442 return (0);
21443
21444 /*
21445 * Validate values, create default attributes, evaluate IDCs.
21446 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021447 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21448 attr = vctxt->attrInfos[i];
21449 /*
21450 * VAL TODO: Note that we won't try to resolve IDCs to
21451 * "lax" and "skip" validated attributes. Check what to
21452 * do in this case.
21453 */
21454 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21455 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21456 continue;
21457 /*
21458 * VAL TODO: What to do if the type definition is missing?
21459 */
21460 if (attr->typeDef == NULL) {
21461 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21462 continue;
21463 }
21464
21465 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021466 fixed = 0;
21467 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021468
21469 if (vctxt->xpathStates != NULL) {
21470 /*
21471 * Evaluate IDCs.
21472 */
21473 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21474 XML_ATTRIBUTE_NODE);
21475 if (xpathRes == -1) {
21476 VERROR_INT("xmlSchemaVAttributesComplex",
21477 "calling xmlSchemaXPathEvaluate()");
21478 goto internal_error;
21479 }
21480 }
21481
21482 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21483 /*
21484 * Default/fixed attributes.
21485 */
21486 if (xpathRes) {
21487 if (attr->use->defValue == NULL) {
21488 attr->value = (xmlChar *) attr->use->defValue;
21489 attr->val = attr->use->defVal;
21490 } else {
21491 attr->value = (xmlChar *) attr->decl->defValue;
21492 attr->val = attr->decl->defVal;
21493 }
21494 /*
21495 * IDCs will consume the precomputed default value,
21496 * so we need to clone it.
21497 */
21498 if (attr->val == NULL) {
21499 VERROR_INT("xmlSchemaVAttributesComplex",
21500 "default/fixed value on an attribute use was "
21501 "not precomputed");
21502 goto internal_error;
21503 }
21504 attr->val = xmlSchemaCopyValue(attr->val);
21505 if (attr->val == NULL) {
21506 VERROR_INT("xmlSchemaVAttributesComplex",
21507 "calling xmlSchemaCopyValue()");
21508 goto internal_error;
21509 }
21510 }
21511 /*
21512 * PSVI: Add the default attribute to the current element.
21513 * VAL TODO: Should we use the *normalized* value? This currently
21514 * uses the *initial* value.
21515 */
21516 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21517 (attr->node != NULL) && (attr->node->doc != NULL)) {
21518 xmlChar *normValue;
21519 const xmlChar *value;
21520
21521 value = attr->value;
21522 /*
21523 * Normalize the value.
21524 */
21525 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21526 attr->value);
21527 if (normValue != NULL)
21528 value = BAD_CAST normValue;
21529
21530 if (attr->nsName == NULL) {
21531 if (xmlNewProp(attr->node->parent,
21532 attr->localName, value) == NULL) {
21533 VERROR_INT("xmlSchemaVAttributesComplex",
21534 "callling xmlNewProp()");
21535 if (normValue != NULL)
21536 xmlFree(normValue);
21537 goto internal_error;
21538 }
21539 } else {
21540 xmlNsPtr ns;
21541
21542 ns = xmlSearchNsByHref(attr->node->doc,
21543 attr->node->parent, attr->nsName);
21544 if (ns == NULL) {
21545 xmlChar prefix[12];
21546 int counter = 0;
21547
21548 /*
21549 * Create a namespace declaration on the validation
21550 * root node if no namespace declaration is in scope.
21551 */
21552 do {
21553 snprintf((char *) prefix, 12, "p%d", counter++);
21554 ns = xmlSearchNs(attr->node->doc,
21555 attr->node->parent, BAD_CAST prefix);
21556 if (counter > 1000) {
21557 VERROR_INT(
21558 "xmlSchemaVAttributesComplex",
21559 "could not compute a ns prefix for a "
21560 "default/fixed attribute");
21561 if (normValue != NULL)
21562 xmlFree(normValue);
21563 goto internal_error;
21564 }
21565 } while (ns != NULL);
21566 ns = xmlNewNs(vctxt->validationRoot,
21567 attr->nsName, BAD_CAST prefix);
21568 }
21569 xmlNewNsProp(attr->node->parent, ns,
21570 attr->localName, value);
21571 }
21572 if (normValue != NULL)
21573 xmlFree(normValue);
21574 }
21575 /*
21576 * Go directly to IDC evaluation.
21577 */
21578 goto eval_idcs;
21579 }
21580 /*
21581 * Validate the value.
21582 */
21583 if (vctxt->value != NULL) {
21584 /*
21585 * Free last computed value; just for safety reasons.
21586 */
21587 xmlSchemaFreeValue(vctxt->value);
21588 vctxt->value = NULL;
21589 }
21590 /*
21591 * Note that the attribute *use* can be unavailable, if
21592 * the attribute was a wild attribute.
21593 */
21594 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21595 ((attr->use != NULL) &&
21596 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21597 fixed = 1;
21598 else
21599 fixed = 0;
21600 /*
21601 * SPEC (cvc-attribute)
21602 * (3) "The item's ·normalized value· must be locally ·valid·
21603 * with respect to that {type definition} as per
21604 * String Valid (§3.14.4)."
21605 *
21606 * VAL TODO: Do we already have the
21607 * "normalized attribute value" here?
21608 */
21609 if (xpathRes || fixed) {
21610 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21611 /*
21612 * Request a computed value.
21613 */
21614 res = xmlSchemaVCheckCVCSimpleType(
21615 (xmlSchemaAbstractCtxtPtr) vctxt,
21616 attr->node, attr->typeDef, attr->value, &(attr->val),
21617 1, 1, 0);
21618 } else {
21619 res = xmlSchemaVCheckCVCSimpleType(
21620 (xmlSchemaAbstractCtxtPtr) vctxt,
21621 attr->node, attr->typeDef, attr->value, NULL,
21622 1, 0, 0);
21623 }
21624
21625 if (res != 0) {
21626 if (res == -1) {
21627 VERROR_INT("xmlSchemaVAttributesComplex",
21628 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21629 goto internal_error;
21630 }
21631 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21632 /*
21633 * SPEC PSVI Assessment Outcome (Attribute)
21634 * [validity] = "invalid"
21635 */
21636 goto eval_idcs;
21637 }
21638
21639 if (fixed) {
21640 int ws;
21641 /*
21642 * SPEC Attribute Locally Valid (Use) (cvc-au)
21643 * "For an attribute information item to be·valid·
21644 * with respect to an attribute use its *normalized*
21645 * value· must match the *canonical* lexical
21646 * representation of the attribute use's {value
21647 * constraint}value, if it is present and fixed."
21648 *
21649 * VAL TODO: The requirement for the *canonical* value
21650 * will be removed in XML Schema 1.1.
21651 */
21652 /*
21653 * SPEC Attribute Locally Valid (cvc-attribute)
21654 * (4) "The item's *actual* value· must match the *value* of
21655 * the {value constraint}, if it is present and fixed."
21656 */
21657 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21658 if (attr->val == NULL) {
21659 /* VAL TODO: A value was not precomputed. */
21660 TODO
21661 goto eval_idcs;
21662 }
21663 if ((attr->use != NULL) &&
21664 (attr->use->defValue != NULL)) {
21665 if (attr->use->defVal == NULL) {
21666 /* VAL TODO: A default value was not precomputed. */
21667 TODO
21668 goto eval_idcs;
21669 }
21670 attr->vcValue = attr->use->defValue;
21671 /*
21672 if (xmlSchemaCompareValuesWhtsp(attr->val,
21673 (xmlSchemaWhitespaceValueType) ws,
21674 attr->use->defVal,
21675 (xmlSchemaWhitespaceValueType) ws) != 0) {
21676 */
21677 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21678 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21679 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021680 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021681 /* VAL TODO: A default value was not precomputed. */
21682 TODO
21683 goto eval_idcs;
21684 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021685 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021686 /*
21687 if (xmlSchemaCompareValuesWhtsp(attr->val,
21688 (xmlSchemaWhitespaceValueType) ws,
21689 attrDecl->defVal,
21690 (xmlSchemaWhitespaceValueType) ws) != 0) {
21691 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021692 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021693 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21694 }
21695 /*
21696 * [validity] = "valid"
21697 */
21698 }
21699eval_idcs:
21700 /*
21701 * Evaluate IDCs.
21702 */
21703 if (xpathRes) {
21704 if (xmlSchemaXPathProcessHistory(vctxt,
21705 vctxt->depth +1) == -1) {
21706 VERROR_INT("xmlSchemaVAttributesComplex",
21707 "calling xmlSchemaXPathEvaluate()");
21708 goto internal_error;
21709 }
21710 }
21711 }
21712
21713 /*
21714 * Report errors.
21715 */
21716 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21717 attr = vctxt->attrInfos[i];
21718 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21719 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21720 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21721 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21722 continue;
21723 ACTIVATE_ATTRIBUTE(attr);
21724 switch (attr->state) {
21725 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21726 xmlChar *str = NULL;
21727 ACTIVATE_ELEM;
21728 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21729 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21730 "The attribute '%s' is required but missing",
21731 xmlSchemaFormatQName(&str,
21732 attr->decl->targetNamespace,
21733 attr->decl->name),
21734 NULL);
21735 FREE_AND_NULL(str)
21736 break;
21737 }
21738 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21739 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21740 "The type definition is absent");
21741 break;
21742 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21743 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21744 XML_SCHEMAV_CVC_AU, NULL, NULL,
21745 "The value '%s' does not match the fixed "
21746 "value constraint '%s'",
21747 attr->value, attr->vcValue);
21748 break;
21749 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21750 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21751 "No matching global attribute declaration available, but "
21752 "demanded by the strict wildcard");
21753 break;
21754 case XML_SCHEMAS_ATTR_UNKNOWN:
21755 if (attr->metaType)
21756 break;
21757 /*
21758 * MAYBE VAL TODO: One might report different error messages
21759 * for the following errors.
21760 */
21761 if (type->attributeWildcard == NULL) {
21762 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21763 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21764 } else {
21765 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21766 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21767 }
21768 break;
21769 default:
21770 break;
21771 }
21772 }
21773
21774 ACTIVATE_ELEM;
21775 return (0);
21776internal_error:
21777 ACTIVATE_ELEM;
21778 return (-1);
21779}
21780
21781static int
21782xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21783 int *skip)
21784{
21785 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21786 /*
21787 * The namespace of the element was already identified to be
21788 * matching the wildcard.
21789 */
21790 if ((skip == NULL) || (wild == NULL) ||
21791 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21792 VERROR_INT("xmlSchemaValidateElemWildcard",
21793 "bad arguments");
21794 return (-1);
21795 }
21796 *skip = 0;
21797 if (wild->negNsSet != NULL) {
21798 /*
21799 * URGENT VAL TODO: Fix the content model to reject
21800 * "##other" wildcards.
21801 */
21802 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21803 vctxt->inode->nsName) != 0) {
21804 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21805 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21806 /*
21807 * VAL TODO: Workaround possible *only* if minOccurs and
21808 * maxOccurs are 1.
21809 */
21810 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21811 /* VAL TODO: error code? */
21812 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21813 (xmlSchemaTypePtr) wild,
21814 "This element is not accepted by the wildcard",
21815 0, 0, NULL);
21816 vctxt->skipDepth = vctxt->depth;
21817 if ((pinode->flags &
21818 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21819 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21820 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21821 return (XML_SCHEMAV_ELEMENT_CONTENT);
21822 }
21823 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21824 *skip = 1;
21825 return (0);
21826 }
21827 vctxt->inode->typeDef =
21828 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21829 return (0);
21830 }
21831 }
21832 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21833 /*
21834 * URGENT VAL TODO: Either we need to position the stream to the
21835 * next sibling, or walk the whole subtree.
21836 */
21837 *skip = 1;
21838 return (0);
21839 }
21840 {
21841 xmlSchemaElementPtr decl = NULL;
21842
21843 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21844 vctxt->inode->localName, vctxt->inode->nsName,
21845 NULL);
21846 if (decl != NULL) {
21847 vctxt->inode->decl = decl;
21848 return (0);
21849 }
21850 }
21851 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21852 /* VAL TODO: Change to proper error code. */
21853 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21854 "No matching global element declaration available, but "
21855 "demanded by the strict wildcard");
21856 return (vctxt->err);
21857 }
21858 if (vctxt->nbAttrInfos != 0) {
21859 xmlSchemaAttrInfoPtr iattr;
21860 /*
21861 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21862 * (1.2.1.2.1) - (1.2.1.2.3 )
21863 *
21864 * Use the xsi:type attribute for the type definition.
21865 */
21866 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21867 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21868 if (iattr != NULL) {
21869 if (xmlSchemaProcessXSIType(vctxt, iattr,
21870 &(vctxt->inode->typeDef), NULL) == -1) {
21871 VERROR_INT("xmlSchemaValidateElemWildcard",
21872 "calling xmlSchemaProcessXSIType() to "
21873 "process the attribute 'xsi:nil'");
21874 return (-1);
21875 }
21876 /*
21877 * Don't return an error on purpose.
21878 */
21879 return (0);
21880 }
21881 }
21882 /*
21883 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21884 *
21885 * Fallback to "anyType".
21886 */
21887 vctxt->inode->typeDef =
21888 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21889 return (0);
21890}
21891
21892/*
21893* xmlSchemaCheckCOSValidDefault:
21894*
21895* This will be called if: not nilled, no content and a default/fixed
21896* value is provided.
21897*/
21898
21899static int
21900xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21901 const xmlChar *value,
21902 xmlSchemaValPtr *val)
21903{
21904 int ret = 0;
21905 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21906
21907 /*
21908 * cos-valid-default:
21909 * Schema Component Constraint: Element Default Valid (Immediate)
21910 * For a string to be a valid default with respect to a type
21911 * definition the appropriate case among the following must be true:
21912 */
21913 if IS_COMPLEX_TYPE(inode->typeDef) {
21914 /*
21915 * Complex type.
21916 *
21917 * SPEC (2.1) "its {content type} must be a simple type definition
21918 * or mixed."
21919 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21920 * type}'s particle must be ·emptiable· as defined by
21921 * Particle Emptiable (§3.9.6)."
21922 */
21923 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21924 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21925 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21926 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21927 /* NOTE that this covers (2.2.2) as well. */
21928 VERROR(ret, NULL,
21929 "For a string to be a valid default, the type definition "
21930 "must be a simple type or a complex type with simple content "
21931 "or mixed content and a particle emptiable");
21932 return(ret);
21933 }
21934 }
21935 /*
21936 * 1 If the type definition is a simple type definition, then the string
21937 * must be ·valid· with respect to that definition as defined by String
21938 * Valid (§3.14.4).
21939 *
21940 * AND
21941 *
21942 * 2.2.1 If the {content type} is a simple type definition, then the
21943 * string must be ·valid· with respect to that simple type definition
21944 * as defined by String Valid (§3.14.4).
21945 */
21946 if (IS_SIMPLE_TYPE(inode->typeDef)) {
21947
21948 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21949 NULL, inode->typeDef, value, val, 1, 1, 0);
21950
21951 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
21952
21953 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
21954 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
21955 }
21956 if (ret < 0) {
21957 VERROR_INT("xmlSchemaCheckCOSValidDefault",
21958 "calling xmlSchemaVCheckCVCSimpleType()");
21959 }
21960 return (ret);
21961}
21962
21963static void
21964xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
21965 const xmlChar * name ATTRIBUTE_UNUSED,
21966 xmlSchemaElementPtr item,
21967 xmlSchemaNodeInfoPtr inode)
21968{
21969 inode->decl = item;
21970#ifdef DEBUG_CONTENT
21971 {
21972 xmlChar *str = NULL;
21973
21974 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
21975 xmlGenericError(xmlGenericErrorContext,
21976 "AUTOMATON callback for '%s' [declaration]\n",
21977 xmlSchemaFormatQName(&str,
21978 inode->localName, inode->nsName));
21979 } else {
21980 xmlGenericError(xmlGenericErrorContext,
21981 "AUTOMATON callback for '%s' [wildcard]\n",
21982 xmlSchemaFormatQName(&str,
21983 inode->localName, inode->nsName));
21984
21985 }
21986 FREE_AND_NULL(str)
21987 }
21988#endif
21989}
21990
21991static int
21992xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000021993{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021994 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
21995 if (vctxt->inode == NULL) {
21996 VERROR_INT("xmlSchemaValidatorPushElem",
21997 "calling xmlSchemaGetFreshElemInfo()");
21998 return (-1);
21999 }
22000 vctxt->nbAttrInfos = 0;
22001 return (0);
22002}
22003
22004static int
22005xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22006 xmlSchemaNodeInfoPtr inode,
22007 xmlSchemaTypePtr type,
22008 const xmlChar *value)
22009{
22010 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22011 return (xmlSchemaVCheckCVCSimpleType(
22012 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22013 type, value, &(inode->val), 1, 1, 0));
22014 else
22015 return (xmlSchemaVCheckCVCSimpleType(
22016 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22017 type, value, NULL, 1, 0, 0));
22018}
22019
22020
22021
22022/*
22023* Process END of element.
22024*/
22025static int
22026xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22027{
22028 int ret = 0;
22029 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22030
22031 if (vctxt->nbAttrInfos != 0)
22032 xmlSchemaClearAttrInfos(vctxt);
22033 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22034 /*
22035 * This element was not expected;
22036 * we will not validate child elements of broken parents.
22037 * Skip validation of all content of the parent.
22038 */
22039 vctxt->skipDepth = vctxt->depth -1;
22040 goto end_elem;
22041 }
22042 if ((inode->typeDef == NULL) ||
22043 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22044 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022045 * 1. the type definition might be missing if the element was
22046 * error prone
22047 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022048 */
22049 goto end_elem;
22050 }
22051 /*
22052 * Check the content model.
22053 */
22054 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22055 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22056
22057 /*
22058 * Workaround for "anyType".
22059 */
22060 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22061 goto character_content;
22062
22063 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22064 xmlChar *values[10];
22065 int terminal, nbval = 10, nbneg;
22066
22067 if (inode->regexCtxt == NULL) {
22068 /*
22069 * Create the regex context.
22070 */
22071 inode->regexCtxt =
22072 xmlRegNewExecCtxt(inode->typeDef->contModel,
22073 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22074 vctxt);
22075 if (inode->regexCtxt == NULL) {
22076 VERROR_INT("xmlSchemaValidatorPopElem",
22077 "failed to create a regex context");
22078 goto internal_error;
22079 }
22080#ifdef DEBUG_AUTOMATA
22081 xmlGenericError(xmlGenericErrorContext,
22082 "AUTOMATON create on '%s'\n", inode->localName);
22083#endif
22084 }
22085 /*
22086 * Get hold of the still expected content, since a further
22087 * call to xmlRegExecPushString() will loose this information.
22088 */
22089 xmlRegExecNextValues(inode->regexCtxt,
22090 &nbval, &nbneg, &values[0], &terminal);
22091 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22092 if (ret <= 0) {
22093 /*
22094 * Still missing something.
22095 */
22096 ret = 1;
22097 inode->flags |=
22098 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22099 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22100 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22101 "Missing child element(s)",
22102 nbval, nbneg, values);
22103#ifdef DEBUG_AUTOMATA
22104 xmlGenericError(xmlGenericErrorContext,
22105 "AUTOMATON missing ERROR on '%s'\n",
22106 inode->localName);
22107#endif
22108 } else {
22109 /*
22110 * Content model is satisfied.
22111 */
22112 ret = 0;
22113#ifdef DEBUG_AUTOMATA
22114 xmlGenericError(xmlGenericErrorContext,
22115 "AUTOMATON succeeded on '%s'\n",
22116 inode->localName);
22117#endif
22118 }
22119
22120 }
22121 }
22122 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22123 goto end_elem;
22124
22125character_content:
22126
22127 if (vctxt->value != NULL) {
22128 xmlSchemaFreeValue(vctxt->value);
22129 vctxt->value = NULL;
22130 }
22131 /*
22132 * Check character content.
22133 */
22134 if (inode->decl == NULL) {
22135 /*
22136 * Speedup if no declaration exists.
22137 */
22138 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22139 ret = xmlSchemaVCheckINodeDataType(vctxt,
22140 inode, inode->typeDef, inode->value);
22141 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22142 ret = xmlSchemaVCheckINodeDataType(vctxt,
22143 inode, inode->typeDef->contentTypeDef,
22144 inode->value);
22145 }
22146 if (ret < 0) {
22147 VERROR_INT("xmlSchemaValidatorPopElem",
22148 "calling xmlSchemaVCheckCVCSimpleType()");
22149 goto internal_error;
22150 }
22151 goto end_elem;
22152 }
22153 /*
22154 * cvc-elt (3.3.4) : 5
22155 * The appropriate case among the following must be true:
22156 */
22157 /*
22158 * cvc-elt (3.3.4) : 5.1
22159 * If the declaration has a {value constraint},
22160 * the item has neither element nor character [children] and
22161 * clause 3.2 has not applied, then all of the following must be true:
22162 */
22163 if ((inode->decl->value != NULL) &&
22164 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22165 (! INODE_NILLED(inode))) {
22166 /*
22167 * cvc-elt (3.3.4) : 5.1.1
22168 * If the ·actual type definition· is a ·local type definition·
22169 * then the canonical lexical representation of the {value constraint}
22170 * value must be a valid default for the ·actual type definition· as
22171 * defined in Element Default Valid (Immediate) (§3.3.6).
22172 */
22173 /*
22174 * NOTE: 'local' above means types aquired by xsi:type.
22175 * NOTE: Although the *canonical* value is stated, it is not
22176 * relevant if canonical or not. Additionally XML Schema 1.1
22177 * will removed this requirement as well.
22178 */
22179 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22180
22181 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22182 inode->decl->value, &(inode->val));
22183 if (ret != 0) {
22184 if (ret < 0) {
22185 VERROR_INT("xmlSchemaValidatorPopElem",
22186 "calling xmlSchemaCheckCOSValidDefault()");
22187 goto internal_error;
22188 }
22189 goto end_elem;
22190 }
22191 /*
22192 * Stop here, to avoid redundant validation of the value
22193 * (see following).
22194 */
22195 goto default_psvi;
22196 }
22197 /*
22198 * cvc-elt (3.3.4) : 5.1.2
22199 * The element information item with the canonical lexical
22200 * representation of the {value constraint} value used as its
22201 * ·normalized value· must be ·valid· with respect to the
22202 * ·actual type definition· as defined by Element Locally Valid (Type)
22203 * (§3.3.4).
22204 */
22205 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22206 ret = xmlSchemaVCheckINodeDataType(vctxt,
22207 inode, inode->typeDef, inode->decl->value);
22208 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22209 ret = xmlSchemaVCheckINodeDataType(vctxt,
22210 inode, inode->typeDef->contentTypeDef,
22211 inode->decl->value);
22212 }
22213 if (ret != 0) {
22214 if (ret < 0) {
22215 VERROR_INT("xmlSchemaValidatorPopElem",
22216 "calling xmlSchemaVCheckCVCSimpleType()");
22217 goto internal_error;
22218 }
22219 goto end_elem;
22220 }
22221
22222default_psvi:
22223 /*
22224 * PSVI: Create a text node on the instance element.
22225 */
22226 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22227 (inode->node != NULL)) {
22228 xmlNodePtr textChild;
22229 xmlChar *normValue;
22230 /*
22231 * VAL TODO: Normalize the value.
22232 */
22233 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22234 inode->decl->value);
22235 if (normValue != NULL) {
22236 textChild = xmlNewText(BAD_CAST normValue);
22237 xmlFree(normValue);
22238 } else
22239 textChild = xmlNewText(inode->decl->value);
22240 if (textChild == NULL) {
22241 VERROR_INT("xmlSchemaValidatorPopElem",
22242 "calling xmlNewText()");
22243 goto internal_error;
22244 } else
22245 xmlAddChild(inode->node, textChild);
22246 }
22247
22248 } else if (! INODE_NILLED(inode)) {
22249 /*
22250 * 5.2.1 The element information item must be ·valid· with respect
22251 * to the ·actual type definition· as defined by Element Locally
22252 * Valid (Type) (§3.3.4).
22253 */
22254 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22255 /*
22256 * SPEC (cvc-type) (3.1)
22257 * "If the type definition is a simple type definition, ..."
22258 * (3.1.3) "If clause 3.2 of Element Locally Valid
22259 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22260 * must be ·valid· with respect to the type definition as defined
22261 * by String Valid (§3.14.4).
22262 */
22263 ret = xmlSchemaVCheckINodeDataType(vctxt,
22264 inode, inode->typeDef, inode->value);
22265 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22266 /*
22267 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22268 * definition, then the element information item must be
22269 * ·valid· with respect to the type definition as per
22270 * Element Locally Valid (Complex Type) (§3.4.4);"
22271 *
22272 * SPEC (cvc-complex-type) (2.2)
22273 * "If the {content type} is a simple type definition, ...
22274 * the ·normalized value· of the element information item is
22275 * ·valid· with respect to that simple type definition as
22276 * defined by String Valid (§3.14.4)."
22277 */
22278 ret = xmlSchemaVCheckINodeDataType(vctxt,
22279 inode, inode->typeDef->contentTypeDef, inode->value);
22280 }
22281 if (ret != 0) {
22282 if (ret < 0) {
22283 VERROR_INT("xmlSchemaValidatorPopElem",
22284 "calling xmlSchemaVCheckCVCSimpleType()");
22285 goto internal_error;
22286 }
22287 goto end_elem;
22288 }
22289 /*
22290 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22291 * not applied, all of the following must be true:
22292 */
22293 if ((inode->decl->value != NULL) &&
22294 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22295
22296 /*
22297 * TODO: We will need a computed value, when comparison is
22298 * done on computed values.
22299 */
22300 /*
22301 * 5.2.2.1 The element information item must have no element
22302 * information item [children].
22303 */
22304 if (inode->flags &
22305 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22306 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22307 VERROR(ret, NULL,
22308 "The content must not containt element nodes since "
22309 "there is a fixed value constraint");
22310 goto end_elem;
22311 } else {
22312 /*
22313 * 5.2.2.2 The appropriate case among the following must
22314 * be true:
22315 */
22316 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22317 /*
22318 * 5.2.2.2.1 If the {content type} of the ·actual type
22319 * definition· is mixed, then the *initial value* of the
22320 * item must match the canonical lexical representation
22321 * of the {value constraint} value.
22322 *
22323 * ... the *initial value* of an element information
22324 * item is the string composed of, in order, the
22325 * [character code] of each character information item in
22326 * the [children] of that element information item.
22327 */
22328 if (! xmlStrEqual(inode->value, inode->decl->value)){
22329 /*
22330 * VAL TODO: Report invalid & expected values as well.
22331 * VAL TODO: Implement the canonical stuff.
22332 */
22333 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22334 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22335 ret, NULL, NULL,
22336 "The initial value '%s' does not match the fixed "
22337 "value constraint '%s'",
22338 inode->value, inode->decl->value);
22339 goto end_elem;
22340 }
22341 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22342 /*
22343 * 5.2.2.2.2 If the {content type} of the ·actual type
22344 * definition· is a simple type definition, then the
22345 * *actual value* of the item must match the canonical
22346 * lexical representation of the {value constraint} value.
22347 */
22348 /*
22349 * VAL TODO: *actual value* is the normalized value, impl.
22350 * this.
22351 * VAL TODO: Report invalid & expected values as well.
22352 * VAL TODO: Implement a comparison with the computed values.
22353 */
22354 if (! xmlStrEqual(inode->value,
22355 inode->decl->value)) {
22356 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22357 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22358 ret, NULL, NULL,
22359 "The actual value '%s' does not match the fixed "
22360 "value constraint '%s'",
22361 inode->value,
22362 inode->decl->value);
22363 goto end_elem;
22364 }
22365 }
22366 }
22367 }
22368 }
22369
22370end_elem:
22371 if (vctxt->depth < 0) {
22372 /* TODO: raise error? */
22373 return (0);
22374 }
22375 if (vctxt->depth == vctxt->skipDepth)
22376 vctxt->skipDepth = -1;
22377 /*
22378 * Evaluate the history of XPath state objects.
22379 */
22380 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22381 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022382 /*
22383 * TODO: 6 The element information item must be ·valid· with respect to each of
22384 * the {identity-constraint definitions} as per Identity-constraint
22385 * Satisfied (§3.11.4).
22386 */
22387 /*
22388 * Validate IDC keyrefs.
22389 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022390 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22391 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022392 /*
22393 * Merge/free the IDC table.
22394 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022395 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022396#ifdef DEBUG_IDC
22397 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022398 inode->nsName,
22399 inode->localName,
22400 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022401#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022402 if (vctxt->depth > 0) {
22403 /*
22404 * Merge the IDC node table with the table of the parent node.
22405 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022406 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22407 goto internal_error;
22408 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022409 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022410 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022411 * Clear the current ielem.
22412 * VAL TODO: Don't free the PSVI IDC tables if they are
22413 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022414 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022415 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022416 /*
22417 * Skip further processing if we are on the validation root.
22418 */
22419 if (vctxt->depth == 0) {
22420 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022421 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022422 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022423 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022424 /*
22425 * Reset the bubbleDepth if needed.
22426 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022427 if (vctxt->aidcs != NULL) {
22428 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22429 do {
22430 if (aidc->bubbleDepth == vctxt->depth) {
22431 /*
22432 * A bubbleDepth of a key/unique IDC matches the current
22433 * depth, this means that we are leaving the scope of the
22434 * top-most keyref IDC.
22435 */
22436 aidc->bubbleDepth = -1;
22437 }
22438 aidc = aidc->next;
22439 } while (aidc != NULL);
22440 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022441 vctxt->depth--;
22442 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022443 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022444 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022445 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22446 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022447 return (ret);
22448
22449internal_error:
22450 vctxt->err = -1;
22451 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022452}
22453
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022454/*
22455* 3.4.4 Complex Type Definition Validation Rules
22456* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22457*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022458static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022459xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022460{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022461 xmlSchemaNodeInfoPtr pielem;
22462 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022463 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022464
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022465 if (vctxt->depth <= 0) {
22466 VERROR_INT("xmlSchemaValidateChildElem",
22467 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022468 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022469 }
22470 pielem = vctxt->elemInfos[vctxt->depth -1];
22471 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22472 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022473 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022474 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022475 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022476 if (INODE_NILLED(pielem)) {
22477 /*
22478 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22479 */
22480 ACTIVATE_PARENT_ELEM;
22481 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22482 VERROR(ret, NULL,
22483 "Neither character nor element content is allowed, "
22484 "because the element was 'nilled'");
22485 ACTIVATE_ELEM;
22486 goto unexpected_elem;
22487 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022488
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022489 ptype = pielem->typeDef;
22490
22491 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22492 /*
22493 * Workaround for "anyType": we have currently no content model
22494 * assigned for "anyType", so handle it explicitely.
22495 * "anyType" has an unbounded, lax "any" wildcard.
22496 */
22497 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22498 vctxt->inode->localName,
22499 vctxt->inode->nsName);
22500
22501 if (vctxt->inode->decl == NULL) {
22502 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022503 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022504 * Process "xsi:type".
22505 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022506 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022507 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22508 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22509 if (iattr != NULL) {
22510 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22511 &(vctxt->inode->typeDef), NULL);
22512 if (ret != 0) {
22513 if (ret == -1) {
22514 VERROR_INT("xmlSchemaValidateChildElem",
22515 "calling xmlSchemaProcessXSIType() to "
22516 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022517 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022518 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022519 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022520 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022521 } else {
22522 /*
22523 * Fallback to "anyType".
22524 *
22525 * SPEC (cvc-assess-elt)
22526 * "If the item cannot be ·strictly assessed·, [...]
22527 * an element information item's schema validity may be laxly
22528 * assessed if its ·context-determined declaration· is not
22529 * skip by ·validating· with respect to the ·ur-type
22530 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22531 */
22532 vctxt->inode->typeDef =
22533 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022534 }
22535 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022536 return (0);
22537 }
22538
22539 switch (ptype->contentType) {
22540 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022541 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022542 * SPEC (2.1) "If the {content type} is empty, then the
22543 * element information item has no character or element
22544 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022545 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022546 ACTIVATE_PARENT_ELEM
22547 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22548 VERROR(ret, NULL,
22549 "Element content is not allowed, "
22550 "because the content type is empty");
22551 ACTIVATE_ELEM
22552 goto unexpected_elem;
22553 break;
22554
22555 case XML_SCHEMA_CONTENT_MIXED:
22556 case XML_SCHEMA_CONTENT_ELEMENTS: {
22557 xmlRegExecCtxtPtr regexCtxt;
22558 xmlChar *values[10];
22559 int terminal, nbval = 10, nbneg;
22560
22561 /* VAL TODO: Optimized "anyType" validation.*/
22562
22563 if (ptype->contModel == NULL) {
22564 VERROR_INT("xmlSchemaValidateChildElem",
22565 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022566 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022567 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022568 /*
22569 * Safety belf for evaluation if the cont. model was already
22570 * examined to be invalid.
22571 */
22572 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22573 VERROR_INT("xmlSchemaValidateChildElem",
22574 "validating elem, but elem content is already invalid");
22575 return (-1);
22576 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022577
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022578 regexCtxt = pielem->regexCtxt;
22579 if (regexCtxt == NULL) {
22580 /*
22581 * Create the regex context.
22582 */
22583 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22584 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22585 vctxt);
22586 if (regexCtxt == NULL) {
22587 VERROR_INT("xmlSchemaValidateChildElem",
22588 "failed to create a regex context");
22589 return (-1);
22590 }
22591 pielem->regexCtxt = regexCtxt;
22592#ifdef DEBUG_AUTOMATA
22593 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22594 pielem->localName);
22595#endif
22596 }
22597
22598 /*
22599 * SPEC (2.4) "If the {content type} is element-only or mixed,
22600 * then the sequence of the element information item's
22601 * element information item [children], if any, taken in
22602 * order, is ·valid· with respect to the {content type}'s
22603 * particle, as defined in Element Sequence Locally Valid
22604 * (Particle) (§3.9.4)."
22605 */
22606 ret = xmlRegExecPushString2(regexCtxt,
22607 vctxt->inode->localName,
22608 vctxt->inode->nsName,
22609 vctxt->inode);
22610#ifdef DEBUG_AUTOMATA
22611 if (ret < 0)
22612 xmlGenericError(xmlGenericErrorContext,
22613 "AUTOMATON push ERROR for '%s' on '%s'\n",
22614 vctxt->inode->localName, pielem->localName);
22615 else
22616 xmlGenericError(xmlGenericErrorContext,
22617 "AUTOMATON push OK for '%s' on '%s'\n",
22618 vctxt->inode->localName, pielem->localName);
22619#endif
22620 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22621 VERROR_INT("xmlSchemaValidateChildElem",
22622 "calling xmlRegExecPushString2()");
22623 return (-1);
22624 }
22625 if (ret < 0) {
22626 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22627 &values[0], &terminal);
22628 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22629 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22630 "This element is not expected",
22631 nbval, nbneg, values);
22632 ret = vctxt->err;
22633 goto unexpected_elem;
22634 } else
22635 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022636 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022637 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022638 case XML_SCHEMA_CONTENT_SIMPLE:
22639 case XML_SCHEMA_CONTENT_BASIC:
22640 ACTIVATE_PARENT_ELEM
22641 if (IS_COMPLEX_TYPE(ptype)) {
22642 /*
22643 * SPEC (cvc-complex-type) (2.2)
22644 * "If the {content type} is a simple type definition, then
22645 * the element information item has no element information
22646 * item [children], ..."
22647 */
22648 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22649 VERROR(ret, NULL, "Element content is not allowed, "
22650 "because the content type is a simple type definition");
22651 } else {
22652 /*
22653 * SPEC (cvc-type) (3.1.2) "The element information item must
22654 * have no element information item [children]."
22655 */
22656 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22657 VERROR(ret, NULL, "Element content is not allowed, "
22658 "because the type definition is simple");
22659 }
22660 ACTIVATE_ELEM
22661 ret = vctxt->err;
22662 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022663 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022664
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022665 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022666 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022667 }
22668 return (ret);
22669unexpected_elem:
22670 /*
22671 * Pop this element and set the skipDepth to skip
22672 * all further content of the parent element.
22673 */
22674 vctxt->skipDepth = vctxt->depth;
22675 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22676 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22677 return (ret);
22678}
22679
22680#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22681#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22682#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22683
22684static int
22685xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22686 int nodeType, const xmlChar *value, int len,
22687 int mode, int *consumed)
22688{
22689 /*
22690 * Unfortunately we have to duplicate the text sometimes.
22691 * OPTIMIZE: Maybe we could skip it, if:
22692 * 1. content type is simple
22693 * 2. whitespace is "collapse"
22694 * 3. it consists of whitespace only
22695 *
22696 * Process character content.
22697 */
22698 if (consumed != NULL)
22699 *consumed = 0;
22700 if (INODE_NILLED(vctxt->inode)) {
22701 /*
22702 * SPEC cvc-elt (3.3.4 - 3.2.1)
22703 * "The element information item must have no character or
22704 * element information item [children]."
22705 */
22706 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22707 "Neither character nor element content is allowed "
22708 "because the element is 'nilled'");
22709 return (vctxt->err);
22710 }
22711 /*
22712 * SPEC (2.1) "If the {content type} is empty, then the
22713 * element information item has no character or element
22714 * information item [children]."
22715 */
22716 if (vctxt->inode->typeDef->contentType ==
22717 XML_SCHEMA_CONTENT_EMPTY) {
22718 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22719 "Character content is not allowed, "
22720 "because the content type is empty");
22721 return (vctxt->err);
22722 }
22723
22724 if (vctxt->inode->typeDef->contentType ==
22725 XML_SCHEMA_CONTENT_ELEMENTS) {
22726 if ((nodeType != XML_TEXT_NODE) ||
22727 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22728 /*
22729 * SPEC cvc-complex-type (2.3)
22730 * "If the {content type} is element-only, then the
22731 * element information item has no character information
22732 * item [children] other than those whose [character
22733 * code] is defined as a white space in [XML 1.0 (Second
22734 * Edition)]."
22735 */
22736 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22737 "Character content other than whitespace is not allowed "
22738 "because the content type is 'element-only'");
22739 return (vctxt->err);
22740 }
22741 return (0);
22742 }
22743
22744 if ((value == NULL) || (value[0] == 0))
22745 return (0);
22746 /*
22747 * Save the value.
22748 * NOTE that even if the content type is *mixed*, we need the
22749 * *initial value* for default/fixed value constraints.
22750 */
22751 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22752 ((vctxt->inode->decl == NULL) ||
22753 (vctxt->inode->decl->value == NULL)))
22754 return (0);
22755
22756 if (vctxt->inode->value == NULL) {
22757 /*
22758 * Set the value.
22759 */
22760 switch (mode) {
22761 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22762 /*
22763 * When working on a tree.
22764 */
22765 vctxt->inode->value = value;
22766 break;
22767 case XML_SCHEMA_PUSH_TEXT_CREATED:
22768 /*
22769 * When working with the reader.
22770 * The value will be freed by the element info.
22771 */
22772 vctxt->inode->value = value;
22773 if (consumed != NULL)
22774 *consumed = 1;
22775 vctxt->inode->flags |=
22776 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22777 break;
22778 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22779 /*
22780 * When working with SAX.
22781 * The value will be freed by the element info.
22782 */
22783 if (len != -1)
22784 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22785 else
22786 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22787 vctxt->inode->flags |=
22788 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22789 break;
22790 default:
22791 break;
22792 }
22793 } else {
22794 /*
22795 * Concat the value.
22796 */
22797 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022798 vctxt->inode->value = BAD_CAST xmlStrncat(
22799 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022800 } else {
22801 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022802 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022803 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22804 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022805 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022806
22807 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022808}
22809
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022810static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022811xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022812{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022813 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022815 if ((vctxt->skipDepth != -1) &&
22816 (vctxt->depth >= vctxt->skipDepth)) {
22817 VERROR_INT("xmlSchemaValidateElem",
22818 "in skip-state");
22819 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022820 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022821 if (vctxt->xsiAssemble) {
22822 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22823 goto internal_error;
22824 }
22825 if (vctxt->depth > 0) {
22826 /*
22827 * Validate this element against the content model
22828 * of the parent.
22829 */
22830 ret = xmlSchemaValidateChildElem(vctxt);
22831 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022832 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022833 VERROR_INT("xmlSchemaValidateElem",
22834 "calling xmlSchemaStreamValidateChildElement()");
22835 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022836 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022837 goto exit;
22838 }
22839 if (vctxt->depth == vctxt->skipDepth)
22840 goto exit;
22841 if ((vctxt->inode->decl == NULL) &&
22842 (vctxt->inode->typeDef == NULL)) {
22843 VERROR_INT("xmlSchemaValidateElem",
22844 "the child element was valid but neither the "
22845 "declaration nor the type was set");
22846 goto internal_error;
22847 }
22848 } else {
22849 /*
22850 * Get the declaration of the validation root.
22851 */
22852 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22853 vctxt->inode->localName,
22854 vctxt->inode->nsName);
22855 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022856 ret = XML_SCHEMAV_CVC_ELT_1;
22857 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022858 "No matching global declaration available "
22859 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022860 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022861 }
22862 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022863
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022864 if (vctxt->inode->decl == NULL)
22865 goto type_validation;
22866
22867 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22868 int skip;
22869 /*
22870 * Wildcards.
22871 */
22872 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22873 if (ret != 0) {
22874 if (ret < 0) {
22875 VERROR_INT("xmlSchemaValidateElem",
22876 "calling xmlSchemaValidateElemWildcard()");
22877 goto internal_error;
22878 }
22879 goto exit;
22880 }
22881 if (skip) {
22882 vctxt->skipDepth = vctxt->depth;
22883 goto exit;
22884 }
22885 /*
22886 * The declaration might be set by the wildcard validation,
22887 * when the processContents is "lax" or "strict".
22888 */
22889 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22890 /*
22891 * Clear the "decl" field to not confuse further processing.
22892 */
22893 vctxt->inode->decl = NULL;
22894 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022895 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022896 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022897 /*
22898 * Validate against the declaration.
22899 */
22900 ret = xmlSchemaValidateElemDecl(vctxt);
22901 if (ret != 0) {
22902 if (ret < 0) {
22903 VERROR_INT("xmlSchemaValidateElem",
22904 "calling xmlSchemaValidateElemDecl()");
22905 goto internal_error;
22906 }
22907 goto exit;
22908 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022909 /*
22910 * Validate against the type definition.
22911 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022912type_validation:
22913
22914 if (vctxt->inode->typeDef == NULL) {
22915 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22916 ret = XML_SCHEMAV_CVC_TYPE_1;
22917 VERROR(ret, NULL,
22918 "The type definition is absent");
22919 goto exit;
22920 }
22921 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22922 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22923 ret = XML_SCHEMAV_CVC_TYPE_2;
22924 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022925 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022926 goto exit;
22927 }
22928 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022929 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022930 * during validation against the declaration. This must be done
22931 * _before_ attribute validation.
22932 */
22933 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22934 if (ret == -1) {
22935 VERROR_INT("xmlSchemaValidateElem",
22936 "calling xmlSchemaXPathEvaluate()");
22937 goto internal_error;
22938 }
22939 /*
22940 * Validate attributes.
22941 */
22942 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22943 if ((vctxt->nbAttrInfos != 0) ||
22944 (vctxt->inode->typeDef->attributeUses != NULL)) {
22945
22946 ret = xmlSchemaVAttributesComplex(vctxt);
22947 }
22948 } else if (vctxt->nbAttrInfos != 0) {
22949
22950 ret = xmlSchemaVAttributesSimple(vctxt);
22951 }
22952 /*
22953 * Clear registered attributes.
22954 */
22955 if (vctxt->nbAttrInfos != 0)
22956 xmlSchemaClearAttrInfos(vctxt);
22957 if (ret == -1) {
22958 VERROR_INT("xmlSchemaValidateElem",
22959 "calling attributes validation");
22960 goto internal_error;
22961 }
22962 /*
22963 * Don't return an error if attributes are invalid on purpose.
22964 */
22965 ret = 0;
22966
22967exit:
22968 if (ret != 0)
22969 vctxt->skipDepth = vctxt->depth;
22970 return (ret);
22971internal_error:
22972 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022973}
22974
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022975#ifdef XML_SCHEMA_READER_ENABLED
22976static int
22977xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022978{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022979 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
22980 int depth, nodeType, ret = 0, consumed;
22981 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000022982
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022983 vctxt->depth = -1;
22984 ret = xmlTextReaderRead(vctxt->reader);
22985 /*
22986 * Move to the document element.
22987 */
22988 while (ret == 1) {
22989 nodeType = xmlTextReaderNodeType(vctxt->reader);
22990 if (nodeType == XML_ELEMENT_NODE)
22991 goto root_found;
22992 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022993 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022994 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022995
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022996root_found:
22997
22998 do {
22999 depth = xmlTextReaderDepth(vctxt->reader);
23000 nodeType = xmlTextReaderNodeType(vctxt->reader);
23001
23002 if (nodeType == XML_ELEMENT_NODE) {
23003
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023004 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023005 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23006 VERROR_INT("xmlSchemaVReaderWalk",
23007 "calling xmlSchemaValidatorPushElem()");
23008 goto internal_error;
23009 }
23010 ielem = vctxt->inode;
23011 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23012 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23013 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23014 /*
23015 * Is the element empty?
23016 */
23017 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23018 if (ret == -1) {
23019 VERROR_INT("xmlSchemaVReaderWalk",
23020 "calling xmlTextReaderIsEmptyElement()");
23021 goto internal_error;
23022 }
23023 if (ret) {
23024 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23025 }
23026 /*
23027 * Register attributes.
23028 */
23029 vctxt->nbAttrInfos = 0;
23030 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23031 if (ret == -1) {
23032 VERROR_INT("xmlSchemaVReaderWalk",
23033 "calling xmlTextReaderMoveToFirstAttribute()");
23034 goto internal_error;
23035 }
23036 if (ret == 1) {
23037 do {
23038 /*
23039 * VAL TODO: How do we know that the reader works on a
23040 * node tree, to be able to pass a node here?
23041 */
23042 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23043 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23044 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23045 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23046
23047 VERROR_INT("xmlSchemaVReaderWalk",
23048 "calling xmlSchemaValidatorPushAttribute()");
23049 goto internal_error;
23050 }
23051 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23052 if (ret == -1) {
23053 VERROR_INT("xmlSchemaVReaderWalk",
23054 "calling xmlTextReaderMoveToFirstAttribute()");
23055 goto internal_error;
23056 }
23057 } while (ret == 1);
23058 /*
23059 * Back to element position.
23060 */
23061 ret = xmlTextReaderMoveToElement(vctxt->reader);
23062 if (ret == -1) {
23063 VERROR_INT("xmlSchemaVReaderWalk",
23064 "calling xmlTextReaderMoveToElement()");
23065 goto internal_error;
23066 }
23067 }
23068 /*
23069 * Validate the element.
23070 */
23071 ret= xmlSchemaValidateElem(vctxt);
23072 if (ret != 0) {
23073 if (ret == -1) {
23074 VERROR_INT("xmlSchemaVReaderWalk",
23075 "calling xmlSchemaValidateElem()");
23076 goto internal_error;
23077 }
23078 goto exit;
23079 }
23080 if (vctxt->depth == vctxt->skipDepth) {
23081 int curDepth;
23082 /*
23083 * Skip all content.
23084 */
23085 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23086 ret = xmlTextReaderRead(vctxt->reader);
23087 curDepth = xmlTextReaderDepth(vctxt->reader);
23088 while ((ret == 1) && (curDepth != depth)) {
23089 ret = xmlTextReaderRead(vctxt->reader);
23090 curDepth = xmlTextReaderDepth(vctxt->reader);
23091 }
23092 if (ret < 0) {
23093 /*
23094 * VAL TODO: A reader error occured; what to do here?
23095 */
23096 ret = 1;
23097 goto exit;
23098 }
23099 }
23100 goto leave_elem;
23101 }
23102 /*
23103 * READER VAL TODO: Is an END_ELEM really never called
23104 * if the elem is empty?
23105 */
23106 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23107 goto leave_elem;
23108 } else if (nodeType == END_ELEM) {
23109 /*
23110 * Process END of element.
23111 */
23112leave_elem:
23113 ret = xmlSchemaValidatorPopElem(vctxt);
23114 if (ret != 0) {
23115 if (ret < 0) {
23116 VERROR_INT("xmlSchemaVReaderWalk",
23117 "calling xmlSchemaValidatorPopElem()");
23118 goto internal_error;
23119 }
23120 goto exit;
23121 }
23122 if (vctxt->depth >= 0)
23123 ielem = vctxt->inode;
23124 else
23125 ielem = NULL;
23126 } else if ((nodeType == XML_TEXT_NODE) ||
23127 (nodeType == XML_CDATA_SECTION_NODE) ||
23128 (nodeType == WHTSP) ||
23129 (nodeType == SIGN_WHTSP)) {
23130 /*
23131 * Process character content.
23132 */
23133 xmlChar *value;
23134
23135 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23136 nodeType = XML_TEXT_NODE;
23137
23138 value = xmlTextReaderValue(vctxt->reader);
23139 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23140 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23141 if (! consumed)
23142 xmlFree(value);
23143 if (ret == -1) {
23144 VERROR_INT("xmlSchemaVReaderWalk",
23145 "calling xmlSchemaVPushText()");
23146 goto internal_error;
23147 }
23148 } else if ((nodeType == XML_ENTITY_NODE) ||
23149 (nodeType == XML_ENTITY_REF_NODE)) {
23150 /*
23151 * VAL TODO: What to do with entities?
23152 */
23153 TODO
23154 }
23155 /*
23156 * Read next node.
23157 */
23158 ret = xmlTextReaderRead(vctxt->reader);
23159 } while (ret == 1);
23160
23161exit:
23162 return (ret);
23163internal_error:
23164 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023165}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023166#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023167
23168/************************************************************************
23169 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023170 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023171 * *
23172 ************************************************************************/
23173
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023174#ifdef XML_SCHEMA_SAX_ENABLED
23175/*
23176* Process text content.
23177*/
23178static void
23179xmlSchemaSAXHandleText(void *ctx,
23180 const xmlChar * ch,
23181 int len)
23182{
23183 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23184
23185 if (vctxt->depth < 0)
23186 return;
23187 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23188 return;
23189 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23190 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23191 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23192 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23193 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23194 "calling xmlSchemaVPushText()");
23195 vctxt->err = -1;
23196 xmlStopParser(vctxt->parserCtxt);
23197 }
23198}
23199
23200/*
23201* Process CDATA content.
23202*/
23203static void
23204xmlSchemaSAXHandleCDataSection(void *ctx,
23205 const xmlChar * ch,
23206 int len)
23207{
23208 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23209
23210 if (vctxt->depth < 0)
23211 return;
23212 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23213 return;
23214 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23215 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23216 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23217 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23218 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23219 "calling xmlSchemaVPushText()");
23220 vctxt->err = -1;
23221 xmlStopParser(vctxt->parserCtxt);
23222 }
23223}
23224
23225static void
23226xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23227 const xmlChar * name ATTRIBUTE_UNUSED)
23228{
23229 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23230
23231 if (vctxt->depth < 0)
23232 return;
23233 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23234 return;
23235 /* SAX VAL TODO: What to do here? */
23236 TODO
23237}
23238
23239static void
23240xmlSchemaSAXHandleStartElementNs(void *ctx,
23241 const xmlChar * localname,
23242 const xmlChar * prefix ATTRIBUTE_UNUSED,
23243 const xmlChar * URI,
23244 int nb_namespaces,
23245 const xmlChar ** namespaces,
23246 int nb_attributes,
23247 int nb_defaulted ATTRIBUTE_UNUSED,
23248 const xmlChar ** attributes)
23249{
23250 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23251 int ret;
23252 xmlSchemaNodeInfoPtr ielem;
23253 int i, j;
23254
23255 /*
23256 * SAX VAL TODO: What to do with nb_defaulted?
23257 */
23258 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023259 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023260 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023261 vctxt->depth++;
23262 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023263 return;
23264 /*
23265 * Push the element.
23266 */
23267 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23268 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23269 "calling xmlSchemaValidatorPushElem()");
23270 goto internal_error;
23271 }
23272 ielem = vctxt->inode;
23273 ielem->localName = localname;
23274 ielem->nsName = URI;
23275 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23276 /*
23277 * Register namespaces on the elem info.
23278 */
23279 if (nb_namespaces != 0) {
23280 /*
23281 * Although the parser builds its own namespace list,
23282 * we have no access to it, so we'll use an own one.
23283 */
23284 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23285 /*
23286 * Store prefix and namespace name.
23287 */
23288 if (ielem->nsBindings == NULL) {
23289 ielem->nsBindings =
23290 (const xmlChar **) xmlMalloc(10 *
23291 sizeof(const xmlChar *));
23292 if (ielem->nsBindings == NULL) {
23293 xmlSchemaVErrMemory(vctxt,
23294 "allocating namespace bindings for SAX validation",
23295 NULL);
23296 goto internal_error;
23297 }
23298 ielem->nbNsBindings = 0;
23299 ielem->sizeNsBindings = 5;
23300 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23301 ielem->sizeNsBindings *= 2;
23302 ielem->nsBindings =
23303 (const xmlChar **) xmlRealloc(
23304 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023305 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023306 if (ielem->nsBindings == NULL) {
23307 xmlSchemaVErrMemory(vctxt,
23308 "re-allocating namespace bindings for SAX validation",
23309 NULL);
23310 goto internal_error;
23311 }
23312 }
23313
23314 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23315 if (namespaces[j+1][0] == 0) {
23316 /*
23317 * Handle xmlns="".
23318 */
23319 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23320 } else
23321 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23322 namespaces[j+1];
23323 ielem->nbNsBindings++;
23324 }
23325 }
23326 /*
23327 * Register attributes.
23328 * SAX VAL TODO: We are not adding namespace declaration
23329 * attributes yet.
23330 */
23331 if (nb_attributes != 0) {
23332 xmlChar *value;
23333
23334 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23335 /*
23336 * Duplicate the value.
23337 */
23338 value = xmlStrndup(attributes[j+3],
23339 attributes[j+4] - attributes[j+3]);
23340 ret = xmlSchemaValidatorPushAttribute(vctxt,
23341 NULL, attributes[j], attributes[j+2], 0,
23342 value, 1);
23343 if (ret == -1) {
23344 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23345 "calling xmlSchemaValidatorPushAttribute()");
23346 goto internal_error;
23347 }
23348 }
23349 }
23350 /*
23351 * Validate the element.
23352 */
23353 ret = xmlSchemaValidateElem(vctxt);
23354 if (ret != 0) {
23355 if (ret == -1) {
23356 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23357 "calling xmlSchemaValidateElem()");
23358 goto internal_error;
23359 }
23360 goto exit;
23361 }
23362
23363exit:
23364 return;
23365internal_error:
23366 vctxt->err = -1;
23367 xmlStopParser(vctxt->parserCtxt);
23368 return;
23369}
23370
23371static void
23372xmlSchemaSAXHandleEndElementNs(void *ctx,
23373 const xmlChar * localname ATTRIBUTE_UNUSED,
23374 const xmlChar * prefix ATTRIBUTE_UNUSED,
23375 const xmlChar * URI ATTRIBUTE_UNUSED)
23376{
23377 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23378 int res;
23379
23380 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023381 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023382 */
23383 if (vctxt->skipDepth != -1) {
23384 if (vctxt->depth > vctxt->skipDepth) {
23385 vctxt->depth--;
23386 return;
23387 } else
23388 vctxt->skipDepth = -1;
23389 }
23390 /*
23391 * SAX VAL TODO: Just a temporary check.
23392 */
23393 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23394 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23395 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23396 "elem pop mismatch");
23397 }
23398 res = xmlSchemaValidatorPopElem(vctxt);
23399 if (res != 0) {
23400 if (res < 0) {
23401 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23402 "calling xmlSchemaValidatorPopElem()");
23403 goto internal_error;
23404 }
23405 goto exit;
23406 }
23407exit:
23408 return;
23409internal_error:
23410 vctxt->err = -1;
23411 xmlStopParser(vctxt->parserCtxt);
23412 return;
23413}
23414#endif
23415
Daniel Veillard4255d502002-04-16 15:50:10 +000023416/************************************************************************
23417 * *
23418 * Validation interfaces *
23419 * *
23420 ************************************************************************/
23421
23422/**
23423 * xmlSchemaNewValidCtxt:
23424 * @schema: a precompiled XML Schemas
23425 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023426 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023427 *
23428 * Returns the validation context or NULL in case of error
23429 */
23430xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023431xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23432{
Daniel Veillard4255d502002-04-16 15:50:10 +000023433 xmlSchemaValidCtxtPtr ret;
23434
23435 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23436 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023437 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023438 return (NULL);
23439 }
23440 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023441 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23442 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023443 return (ret);
23444}
23445
23446/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023447 * xmlSchemaClearValidCtxt:
23448 * @ctxt: the schema validation context
23449 *
23450 * Free the resources associated to the schema validation context;
23451 * leaves some fields alive intended for reuse of the context.
23452 */
23453static void
23454xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23455{
23456 if (vctxt == NULL)
23457 return;
23458
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023459 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023460 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023461 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023462#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023463 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023464#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023465 if (vctxt->value != NULL) {
23466 xmlSchemaFreeValue(vctxt->value);
23467 vctxt->value = NULL;
23468 }
23469 /*
23470 * Augmented IDC information.
23471 */
23472 if (vctxt->aidcs != NULL) {
23473 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23474 do {
23475 next = cur->next;
23476 xmlFree(cur);
23477 cur = next;
23478 } while (cur != NULL);
23479 vctxt->aidcs = NULL;
23480 }
23481 if (vctxt->idcNodes != NULL) {
23482 int i;
23483 xmlSchemaPSVIIDCNodePtr item;
23484
23485 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023486 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023487 xmlFree(item->keys);
23488 xmlFree(item);
23489 }
23490 xmlFree(vctxt->idcNodes);
23491 vctxt->idcNodes = NULL;
23492 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023493 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023494 * Note that we won't delete the XPath state pool here.
23495 */
23496 if (vctxt->xpathStates != NULL) {
23497 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23498 vctxt->xpathStates = NULL;
23499 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023500 /*
23501 * Attribute info.
23502 */
23503 if (vctxt->nbAttrInfos != 0) {
23504 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023505 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023506 /*
23507 * Element info.
23508 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023509 if (vctxt->elemInfos != NULL) {
23510 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023511 xmlSchemaNodeInfoPtr ei;
23512
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023513 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023514 ei = vctxt->elemInfos[i];
23515 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023516 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023517 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023518 }
23519 }
23520}
23521
23522/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023523 * xmlSchemaFreeValidCtxt:
23524 * @ctxt: the schema validation context
23525 *
23526 * Free the resources associated to the schema validation context
23527 */
23528void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023529xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23530{
Daniel Veillard4255d502002-04-16 15:50:10 +000023531 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023532 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023533 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023534 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023535 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023536 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023537 if (ctxt->idcNodes != NULL) {
23538 int i;
23539 xmlSchemaPSVIIDCNodePtr item;
23540
23541 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023542 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023543 xmlFree(item->keys);
23544 xmlFree(item);
23545 }
23546 xmlFree(ctxt->idcNodes);
23547 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023548 if (ctxt->idcKeys != NULL) {
23549 int i;
23550 for (i = 0; i < ctxt->nbIdcKeys; i++)
23551 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23552 xmlFree(ctxt->idcKeys);
23553 }
23554
23555 if (ctxt->xpathStates != NULL)
23556 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23557 if (ctxt->xpathStatePool != NULL)
23558 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23559
23560 /*
23561 * Augmented IDC information.
23562 */
23563 if (ctxt->aidcs != NULL) {
23564 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23565 do {
23566 next = cur->next;
23567 xmlFree(cur);
23568 cur = next;
23569 } while (cur != NULL);
23570 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023571 if (ctxt->attrInfos != NULL) {
23572 int i;
23573 xmlSchemaAttrInfoPtr attr;
23574
23575 /* Just a paranoid call to the cleanup. */
23576 if (ctxt->nbAttrInfos != 0)
23577 xmlSchemaClearAttrInfos(ctxt);
23578 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23579 attr = ctxt->attrInfos[i];
23580 xmlFree(attr);
23581 }
23582 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023583 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023584 if (ctxt->elemInfos != NULL) {
23585 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023586 xmlSchemaNodeInfoPtr ei;
23587
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023588 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023589 ei = ctxt->elemInfos[i];
23590 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023591 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023592 xmlSchemaClearElemInfo(ei);
23593 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023594 }
23595 xmlFree(ctxt->elemInfos);
23596 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023597 if (ctxt->dict != NULL)
23598 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023599 xmlFree(ctxt);
23600}
23601
23602/**
23603 * xmlSchemaSetValidErrors:
23604 * @ctxt: a schema validation context
23605 * @err: the error function
23606 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023607 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023608 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023609 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023610 */
23611void
23612xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023613 xmlSchemaValidityErrorFunc err,
23614 xmlSchemaValidityWarningFunc warn, void *ctx)
23615{
Daniel Veillard4255d502002-04-16 15:50:10 +000023616 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023617 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023618 ctxt->error = err;
23619 ctxt->warning = warn;
23620 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023621 if (ctxt->pctxt != NULL)
23622 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023623}
23624
23625/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023626 * xmlSchemaGetValidErrors:
23627 * @ctxt: a XML-Schema validation context
23628 * @err: the error function result
23629 * @warn: the warning function result
23630 * @ctx: the functions context result
23631 *
23632 * Get the error and warning callback informations
23633 *
23634 * Returns -1 in case of error and 0 otherwise
23635 */
23636int
23637xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23638 xmlSchemaValidityErrorFunc * err,
23639 xmlSchemaValidityWarningFunc * warn, void **ctx)
23640{
23641 if (ctxt == NULL)
23642 return (-1);
23643 if (err != NULL)
23644 *err = ctxt->error;
23645 if (warn != NULL)
23646 *warn = ctxt->warning;
23647 if (ctx != NULL)
23648 *ctx = ctxt->userData;
23649 return (0);
23650}
23651
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023652
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023653/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023654 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023655 * @ctxt: a schema validation context
23656 * @options: a combination of xmlSchemaValidOption
23657 *
23658 * Sets the options to be used during the validation.
23659 *
23660 * Returns 0 in case of success, -1 in case of an
23661 * API error.
23662 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023663int
23664xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23665 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023666
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023667{
23668 int i;
23669
23670 if (ctxt == NULL)
23671 return (-1);
23672 /*
23673 * WARNING: Change the start value if adding to the
23674 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023675 * TODO: Is there an other, more easy to maintain,
23676 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023677 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023678 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023679 if (options & 1<<i)
23680 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023681 }
23682 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023683 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023684}
23685
23686/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023687 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023688 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023689 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023690 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023691 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023692 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023693 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023694int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023695xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023696
23697{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023698 if (ctxt == NULL)
23699 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023700 else
23701 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023702}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023703
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023704static int
23705xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23706{
23707 xmlAttrPtr attr;
23708 int ret = 0;
23709 xmlSchemaNodeInfoPtr ielem = NULL;
23710 xmlNodePtr node, valRoot;
23711 const xmlChar *nsName;
23712
23713 /* DOC VAL TODO: Move this to the start function. */
23714 valRoot = xmlDocGetRootElement(vctxt->doc);
23715 if (valRoot == NULL) {
23716 /* VAL TODO: Error code? */
23717 VERROR(1, NULL, "The document has no document element");
23718 return (1);
23719 }
23720 vctxt->depth = -1;
23721 vctxt->validationRoot = valRoot;
23722 node = valRoot;
23723 while (node != NULL) {
23724 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23725 goto next_sibling;
23726 if (node->type == XML_ELEMENT_NODE) {
23727
23728 /*
23729 * Init the node-info.
23730 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023731 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023732 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23733 goto internal_error;
23734 ielem = vctxt->inode;
23735 ielem->node = node;
23736 ielem->localName = node->name;
23737 if (node->ns != NULL)
23738 ielem->nsName = node->ns->href;
23739 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23740 /*
23741 * Register attributes.
23742 * DOC VAL TODO: We do not register namespace declaration
23743 * attributes yet.
23744 */
23745 vctxt->nbAttrInfos = 0;
23746 if (node->properties != NULL) {
23747 attr = node->properties;
23748 do {
23749 if (attr->ns != NULL)
23750 nsName = attr->ns->href;
23751 else
23752 nsName = NULL;
23753 ret = xmlSchemaValidatorPushAttribute(vctxt,
23754 (xmlNodePtr) attr,
23755 attr->name, nsName, 0,
23756 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23757 if (ret == -1) {
23758 VERROR_INT("xmlSchemaDocWalk",
23759 "calling xmlSchemaValidatorPushAttribute()");
23760 goto internal_error;
23761 }
23762 attr = attr->next;
23763 } while (attr);
23764 }
23765 /*
23766 * Validate the element.
23767 */
23768 ret = xmlSchemaValidateElem(vctxt);
23769 if (ret != 0) {
23770 if (ret == -1) {
23771 VERROR_INT("xmlSchemaDocWalk",
23772 "calling xmlSchemaValidateElem()");
23773 goto internal_error;
23774 }
23775 /*
23776 * Don't stop validation; just skip the content
23777 * of this element.
23778 */
23779 goto leave_node;
23780 }
23781 if ((vctxt->skipDepth != -1) &&
23782 (vctxt->depth >= vctxt->skipDepth))
23783 goto leave_node;
23784 } else if ((node->type == XML_TEXT_NODE) ||
23785 (node->type == XML_CDATA_SECTION_NODE)) {
23786 /*
23787 * Process character content.
23788 */
23789 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23790 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23791 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23792 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23793 if (ret < 0) {
23794 VERROR_INT("xmlSchemaVDocWalk",
23795 "calling xmlSchemaVPushText()");
23796 goto internal_error;
23797 }
23798 /*
23799 * DOC VAL TODO: Should we skip further validation of the
23800 * element content here?
23801 */
23802 } else if ((node->type == XML_ENTITY_NODE) ||
23803 (node->type == XML_ENTITY_REF_NODE)) {
23804 /*
23805 * DOC VAL TODO: What to do with entities?
23806 */
23807 TODO
23808 } else {
23809 goto leave_node;
23810 /*
23811 * DOC VAL TODO: XInclude nodes, etc.
23812 */
23813 }
23814 /*
23815 * Walk the doc.
23816 */
23817 if (node->children != NULL) {
23818 node = node->children;
23819 continue;
23820 }
23821leave_node:
23822 if (node->type == XML_ELEMENT_NODE) {
23823 /*
23824 * Leaving the scope of an element.
23825 */
23826 if (node != vctxt->inode->node) {
23827 VERROR_INT("xmlSchemaVDocWalk",
23828 "element position mismatch");
23829 goto internal_error;
23830 }
23831 ret = xmlSchemaValidatorPopElem(vctxt);
23832 if (ret != 0) {
23833 if (ret < 0) {
23834 VERROR_INT("xmlSchemaVDocWalk",
23835 "calling xmlSchemaValidatorPopElem()");
23836 goto internal_error;
23837 }
23838 }
23839 if (node == valRoot)
23840 goto exit;
23841 }
23842next_sibling:
23843 if (node->next != NULL)
23844 node = node->next;
23845 else {
23846 node = node->parent;
23847 goto leave_node;
23848 }
23849 }
23850
23851exit:
23852 return (ret);
23853internal_error:
23854 return (-1);
23855}
23856
23857static int
23858xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23859{
23860 int ret = 0;
23861
23862 /*
23863 * Some initialization.
23864 */
23865 vctxt->err = 0;
23866 vctxt->nberrors = 0;
23867 vctxt->depth = -1;
23868 vctxt->skipDepth = -1;
23869 /*
23870 * Create a schema + parser if necessary.
23871 */
23872 if (vctxt->schema == NULL) {
23873
23874 if ((vctxt->pctxt == NULL) &&
23875 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23876 return (-1);
23877
23878 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23879 if (vctxt->schema == NULL) {
23880 VERROR_INT("xmlSchemaVStartValidation",
23881 "creating a schema");
23882 return (-1);
23883 }
23884 vctxt->xsiAssemble = 1;
23885 } else
23886 vctxt->xsiAssemble = 0;
23887 /*
23888 * Augment the IDC definitions.
23889 */
23890 if (vctxt->schema->idcDef != NULL) {
23891 xmlHashScan(vctxt->schema->idcDef,
23892 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23893 }
23894 if (vctxt->doc != NULL) {
23895 /*
23896 * Tree validation.
23897 */
23898 ret = xmlSchemaVDocWalk(vctxt);
Daniel Veillard39e5c892005-07-03 22:48:50 +000023899#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023900 } else if (vctxt->reader != NULL) {
23901 /*
23902 * XML Reader validation.
23903 */
23904#ifdef XML_SCHEMA_READER_ENABLED
23905 ret = xmlSchemaVReaderWalk(vctxt);
23906#endif
Daniel Veillard39e5c892005-07-03 22:48:50 +000023907#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023908 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
23909 /*
23910 * SAX validation.
23911 */
23912 /* ret = xmlSAXUserParseFile(ctxt->sax, ctxt, uri); */
23913 ret = xmlParseDocument(vctxt->parserCtxt);
23914 } else {
23915 VERROR_INT("xmlSchemaVStartValidation",
23916 "no instance to validate");
23917 ret = -1;
23918 }
23919
23920 if (vctxt->xsiAssemble) {
23921 if (vctxt->schema != NULL) {
23922 xmlSchemaFree(vctxt->schema);
23923 vctxt->schema = NULL;
23924 }
23925 }
23926 xmlSchemaClearValidCtxt(vctxt);
23927 if (ret == 0)
23928 ret = vctxt->err;
23929 return (ret);
23930}
23931
23932/**
23933 * xmlSchemaValidateOneElement:
23934 * @ctxt: a schema validation context
23935 * @elem: an element node
23936 *
23937 * Validate a branch of a tree, starting with the given @elem.
23938 *
23939 * Returns 0 if the element and its subtree is valid, a positive error
23940 * code number otherwise and -1 in case of an internal or API error.
23941 */
23942int
23943xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
23944{
23945 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
23946 return (-1);
23947
23948 if (ctxt->schema == NULL)
23949 return (-1);
23950
23951 ctxt->doc = elem->doc;
23952 ctxt->node = elem;
23953 ctxt->validationRoot = elem;
23954 return(xmlSchemaVStart(ctxt));
23955}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023956
Daniel Veillard259f0df2004-08-18 09:13:18 +000023957/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023958 * xmlSchemaValidateDoc:
23959 * @ctxt: a schema validation context
23960 * @doc: a parsed document tree
23961 *
23962 * Validate a document tree in memory.
23963 *
23964 * Returns 0 if the document is schemas valid, a positive error code
23965 * number otherwise and -1 in case of internal or API error.
23966 */
23967int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023968xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
23969{
Daniel Veillard4255d502002-04-16 15:50:10 +000023970 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023971 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023972
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023973 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023974 ctxt->node = xmlDocGetRootElement(doc);
23975 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023976 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023977 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
23978 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023979 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023980 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023981 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023982 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023983 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000023984}
23985
Daniel Veillardcdc82732005-07-08 15:04:06 +000023986
23987/************************************************************************
23988 * *
23989 * Function and data for SAX streaming API *
23990 * *
23991 ************************************************************************/
23992typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
23993typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
23994
23995struct _xmlSchemaSplitSAXData {
23996 xmlSAXHandlerPtr user_sax;
23997 void *user_data;
23998 xmlSchemaValidCtxtPtr ctxt;
23999 xmlSAXHandlerPtr schemas_sax;
24000};
24001
24002/* All those functions just bounces to the user provided SAX handlers */
24003static void
24004internalSubsetSplit(void *ctx, const xmlChar *name,
24005 const xmlChar *ExternalID, const xmlChar *SystemID)
24006{
24007 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24008 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24009 (ctxt->user_sax->internalSubset != NULL))
24010 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24011 SystemID);
24012}
24013
24014static int
24015isStandaloneSplit(void *ctx)
24016{
24017 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24018 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24019 (ctxt->user_sax->isStandalone != NULL))
24020 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24021 return(0);
24022}
24023
24024static int
24025hasInternalSubsetSplit(void *ctx)
24026{
24027 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24028 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24029 (ctxt->user_sax->hasInternalSubset != NULL))
24030 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24031 return(0);
24032}
24033
24034static int
24035hasExternalSubsetSplit(void *ctx)
24036{
24037 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24038 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24039 (ctxt->user_sax->hasExternalSubset != NULL))
24040 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24041 return(0);
24042}
24043
24044static void
24045externalSubsetSplit(void *ctx, const xmlChar *name,
24046 const xmlChar *ExternalID, const xmlChar *SystemID)
24047{
24048 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24049 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24050 (ctxt->user_sax->internalSubset != NULL))
24051 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24052 SystemID);
24053}
24054
24055static xmlParserInputPtr
24056resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24057{
24058 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24059 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24060 (ctxt->user_sax->resolveEntity != NULL))
24061 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24062 systemId));
24063 return(NULL);
24064}
24065
24066static xmlEntityPtr
24067getEntitySplit(void *ctx, const xmlChar *name)
24068{
24069 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24070 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24071 (ctxt->user_sax->getEntity != NULL))
24072 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24073 return(NULL);
24074}
24075
24076static xmlEntityPtr
24077getParameterEntitySplit(void *ctx, const xmlChar *name)
24078{
24079 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24080 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24081 (ctxt->user_sax->getParameterEntity != NULL))
24082 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24083 return(NULL);
24084}
24085
24086
24087static void
24088entityDeclSplit(void *ctx, const xmlChar *name, int type,
24089 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24090{
24091 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24092 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24093 (ctxt->user_sax->entityDecl != NULL))
24094 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24095 systemId, content);
24096}
24097
24098static void
24099attributeDeclSplit(void *ctx, const xmlChar * elem,
24100 const xmlChar * name, int type, int def,
24101 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24102{
24103 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24104 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24105 (ctxt->user_sax->attributeDecl != NULL)) {
24106 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24107 def, defaultValue, tree);
24108 } else {
24109 xmlFreeEnumeration(tree);
24110 }
24111}
24112
24113static void
24114elementDeclSplit(void *ctx, const xmlChar *name, int type,
24115 xmlElementContentPtr content)
24116{
24117 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24118 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24119 (ctxt->user_sax->elementDecl != NULL))
24120 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24121}
24122
24123static void
24124notationDeclSplit(void *ctx, const xmlChar *name,
24125 const xmlChar *publicId, const xmlChar *systemId)
24126{
24127 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24128 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24129 (ctxt->user_sax->notationDecl != NULL))
24130 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24131 systemId);
24132}
24133
24134static void
24135unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24136 const xmlChar *publicId, const xmlChar *systemId,
24137 const xmlChar *notationName)
24138{
24139 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24140 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24141 (ctxt->user_sax->unparsedEntityDecl != NULL))
24142 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24143 systemId, notationName);
24144}
24145
24146static void
24147setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24148{
24149 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24150 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24151 (ctxt->user_sax->setDocumentLocator != NULL))
24152 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24153}
24154
24155static void
24156startDocumentSplit(void *ctx)
24157{
24158 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24159 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24160 (ctxt->user_sax->startDocument != NULL))
24161 ctxt->user_sax->startDocument(ctxt->user_data);
24162}
24163
24164static void
24165endDocumentSplit(void *ctx)
24166{
24167 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24168 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24169 (ctxt->user_sax->endDocument != NULL))
24170 ctxt->user_sax->endDocument(ctxt->user_data);
24171}
24172
24173static void
24174processingInstructionSplit(void *ctx, const xmlChar *target,
24175 const xmlChar *data)
24176{
24177 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24178 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24179 (ctxt->user_sax->processingInstruction != NULL))
24180 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24181}
24182
24183static void
24184commentSplit(void *ctx, const xmlChar *value)
24185{
24186 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24187 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24188 (ctxt->user_sax->comment != NULL))
24189 ctxt->user_sax->comment(ctxt->user_data, value);
24190}
24191
24192/*
24193 * Varargs error callbacks to the user application, harder ...
24194 */
24195
24196static void
24197warningSplit(void *ctx, const char *msg, ...) {
24198 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24199 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24200 (ctxt->user_sax->warning != NULL)) {
24201 TODO
24202 }
24203}
24204static void
24205errorSplit(void *ctx, const char *msg, ...) {
24206 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24207 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24208 (ctxt->user_sax->error != NULL)) {
24209 TODO
24210 }
24211}
24212static void
24213fatalErrorSplit(void *ctx, const char *msg, ...) {
24214 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24215 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24216 (ctxt->user_sax->fatalError != NULL)) {
24217 TODO
24218 }
24219}
24220
24221/*
24222 * Those are function where both the user handler and the schemas handler
24223 * need to be called.
24224 */
24225static void
24226charactersSplit(void *ctx, const xmlChar *ch, int len)
24227{
24228 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24229 if (ctxt == NULL)
24230 return;
24231 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24232 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24233 if (ctxt->ctxt != NULL)
24234 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24235}
24236
24237static void
24238ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24239{
24240 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24241 if (ctxt == NULL)
24242 return;
24243 if ((ctxt->user_sax != NULL) &&
24244 (ctxt->user_sax->ignorableWhitespace != NULL))
24245 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24246 if (ctxt->ctxt != NULL)
24247 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24248}
24249
24250static void
24251cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24252{
24253 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24254 if (ctxt == NULL)
24255 return;
24256 if ((ctxt->user_sax != NULL) &&
24257 (ctxt->user_sax->ignorableWhitespace != NULL))
24258 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24259 if (ctxt->ctxt != NULL)
24260 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24261}
24262
24263static void
24264referenceSplit(void *ctx, const xmlChar *name)
24265{
24266 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24267 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24268 (ctxt->user_sax->reference != NULL))
24269 ctxt->user_sax->reference(ctxt->user_data, name);
24270 if (ctxt->ctxt != NULL)
24271 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24272}
24273
24274static void
24275startElementNsSplit(void *ctx, const xmlChar * localname,
24276 const xmlChar * prefix, const xmlChar * URI,
24277 int nb_namespaces, const xmlChar ** namespaces,
24278 int nb_attributes, int nb_defaulted,
24279 const xmlChar ** attributes) {
24280 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24281 if (ctxt == NULL)
24282 return;
24283 if ((ctxt->user_sax != NULL) &&
24284 (ctxt->user_sax->startElementNs != NULL))
24285 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24286 URI, nb_namespaces, namespaces,
24287 nb_attributes, nb_defaulted,
24288 attributes);
24289 if (ctxt->ctxt != NULL)
24290 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24291 URI, nb_namespaces, namespaces,
24292 nb_attributes, nb_defaulted,
24293 attributes);
24294}
24295
24296static void
24297endElementNsSplit(void *ctx, const xmlChar * localname,
24298 const xmlChar * prefix, const xmlChar * URI) {
24299 xmlSchemaSplitSAXDataPtr ctxt = (xmlSchemaSplitSAXDataPtr) ctx;
24300 if (ctxt == NULL)
24301 return;
24302 if ((ctxt->user_sax != NULL) &&
24303 (ctxt->user_sax->endElementNs != NULL))
24304 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24305 if (ctxt->ctxt != NULL)
24306 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24307}
24308
Daniel Veillard4255d502002-04-16 15:50:10 +000024309/**
24310 * xmlSchemaValidateStream:
24311 * @ctxt: a schema validation context
24312 * @input: the input to use for reading the data
24313 * @enc: an optional encoding information
24314 * @sax: a SAX handler for the resulting events
24315 * @user_data: the context to provide to the SAX handler.
24316 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024317 * Validate an input based on a flow of SAX event from the parser
24318 * and forward the events to the @sax handler with the provided @user_data
24319 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024320 *
24321 * Returns 0 if the document is schemas valid, a positive error code
24322 * number otherwise and -1 in case of internal or API error.
24323 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024324int
Daniel Veillard4255d502002-04-16 15:50:10 +000024325xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024326 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24327 xmlSAXHandlerPtr sax, void *user_data)
24328{
Daniel Veillardcdc82732005-07-08 15:04:06 +000024329 xmlSchemaSplitSAXData split_block;
24330 xmlSAXHandler schemas_sax;
24331 xmlSAXHandlerPtr old_sax;
24332 xmlParserCtxtPtr pctxt;
24333 xmlParserInputPtr inputStream;
24334 int ret;
24335
Daniel Veillard4255d502002-04-16 15:50:10 +000024336 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024337 return (-1);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000024338
Daniel Veillardcdc82732005-07-08 15:04:06 +000024339 memset(&schemas_sax, 0, sizeof(xmlSAXHandler));
24340 schemas_sax.initialized = XML_SAX2_MAGIC;
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024341 if (sax == NULL) {
Daniel Veillardcdc82732005-07-08 15:04:06 +000024342 /*
24343 * go direct, no need for the split block and functions.
24344 */
24345 schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24346 schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24347 /*
24348 * Note that we use the same text-function for both, to prevent
24349 * the parser from testing for ignorable whitespace.
24350 */
24351 schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24352 schemas_sax.characters = xmlSchemaSAXHandleText;
24353
24354 schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24355 schemas_sax.reference = xmlSchemaSAXHandleReference;
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024356 /* ctxt->user_data = &split_block; */
Daniel Veillardcdc82732005-07-08 15:04:06 +000024357 } else {
24358 /*
24359 * Return -1 without parsing if passed a SAXv1 block
24360 */
24361 if (sax->initialized != XML_SAX2_MAGIC)
24362 return(-1);
24363 if ((sax->startElementNs == NULL) && (sax->endElementNs == NULL) &&
24364 ((sax->startElement != NULL) || (sax->endElement != NULL)))
24365 return(-1);
24366
24367 /*
24368 * for each callback unused by Schemas initialize it to the Split
24369 * routine only if non NULL in the user block, this can speed up
24370 * things at the SAX level.
24371 */
24372 if (sax->internalSubset != NULL)
24373 schemas_sax.internalSubset = internalSubsetSplit;
24374 if (sax->isStandalone != NULL)
24375 schemas_sax.isStandalone = isStandaloneSplit;
24376 if (sax->hasInternalSubset != NULL)
24377 schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24378 if (sax->hasExternalSubset != NULL)
24379 schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24380 if (sax->resolveEntity != NULL)
24381 schemas_sax.resolveEntity = resolveEntitySplit;
24382 if (sax->getEntity != NULL)
24383 schemas_sax.getEntity = getEntitySplit;
24384 if (sax->entityDecl != NULL)
24385 schemas_sax.entityDecl = entityDeclSplit;
24386 if (sax->notationDecl != NULL)
24387 schemas_sax.notationDecl = notationDeclSplit;
24388 if (sax->attributeDecl != NULL)
24389 schemas_sax.attributeDecl = attributeDeclSplit;
24390 if (sax->elementDecl != NULL)
24391 schemas_sax.elementDecl = elementDeclSplit;
24392 if (sax->unparsedEntityDecl != NULL)
24393 schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24394 if (sax->setDocumentLocator != NULL)
24395 schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24396 if (sax->startDocument != NULL)
24397 schemas_sax.startDocument = startDocumentSplit;
24398 if (sax->endDocument != NULL)
24399 schemas_sax.endDocument = endDocumentSplit;
24400 if (sax->processingInstruction != NULL)
24401 schemas_sax.processingInstruction = processingInstructionSplit;
24402 if (sax->comment != NULL)
24403 schemas_sax.comment = commentSplit;
24404 if (sax->warning != NULL)
24405 schemas_sax.warning = warningSplit;
24406 if (sax->error != NULL)
24407 schemas_sax.error = errorSplit;
24408 if (sax->fatalError != NULL)
24409 schemas_sax.fatalError = fatalErrorSplit;
24410 if (sax->getParameterEntity != NULL)
24411 schemas_sax.getParameterEntity = getParameterEntitySplit;
24412 if (sax->externalSubset != NULL)
24413 schemas_sax.externalSubset = externalSubsetSplit;
24414
24415 /*
24416 * the 6 schemas callback have to go to the splitter functions
24417 * Note that we use the same text-function for ignorableWhitespace
24418 * if possible, to prevent the parser from testing for ignorable
24419 * whitespace.
24420 */
24421 schemas_sax.characters = charactersSplit;
24422 if ((sax->ignorableWhitespace != NULL) &&
24423 (sax->ignorableWhitespace != sax->characters))
24424 schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24425 else
24426 schemas_sax.ignorableWhitespace = charactersSplit;
24427 schemas_sax.cdataBlock = cdataBlockSplit;
24428 schemas_sax.reference = referenceSplit;
24429 schemas_sax.startElementNs = startElementNsSplit;
24430 schemas_sax.endElementNs = endElementNsSplit;
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024431 /* ctxt->user_data = &split_block; */
24432 split_block.user_sax = sax;
24433 split_block.user_data = user_data;
24434 }
Daniel Veillard4255d502002-04-16 15:50:10 +000024435 ctxt->input = input;
24436 ctxt->enc = enc;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024437 ctxt->sax = &schemas_sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024438 /*
24439 * prepare the parser
24440 */
24441 pctxt = xmlNewParserCtxt();
24442 if (pctxt == NULL)
24443 return (-1);
24444 old_sax = pctxt->sax;
24445 pctxt->sax = &schemas_sax;
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024446 if (sax == NULL)
24447 pctxt->userData = (void *) ctxt;
24448 else
24449 pctxt->userData = &split_block;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024450#if 0
24451 if (options)
24452 xmlCtxtUseOptions(pctxt, options);
24453#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024454 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024455
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024456 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024457 if (inputStream == NULL) {
24458 ret = -1;
24459 goto done;
24460 }
24461 inputPush(pctxt, inputStream);
24462 ctxt->parserCtxt = pctxt;
24463 ctxt->input = input;
24464
24465 /*
24466 * Launch the validation
24467 */
24468 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24469 ret = xmlSchemaVStart(ctxt);
24470
24471 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24472 ret = ctxt->parserCtxt->errNo;
24473 if (ret == 0)
24474 ret = 1;
24475 }
24476 ctxt->parserCtxt = NULL;
24477 ctxt->sax = NULL;
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024478 /* ctxt->user_data = NULL; */
Daniel Veillardcdc82732005-07-08 15:04:06 +000024479 ctxt->input = NULL;
24480
24481done:
24482 /* cleanup */
24483 pctxt->sax = old_sax;
24484 xmlFreeParserCtxt(pctxt);
24485 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024486}
24487
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024488/**
24489 * xmlSchemaValidateFile:
24490 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024491 * @filename: the URI of the instance
24492 * @options: a future set of options, currently unused
24493 *
24494 * Do a schemas validation of the given resource, it will use the
24495 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024496 *
24497 * Returns 0 if the document is valid, a positive error code
24498 * number otherwise and -1 in case of an internal or API error.
24499 */
24500int
24501xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024502 const char * filename,
24503 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024504{
Daniel Veillard81562d22005-06-15 13:27:56 +000024505#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024506 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024507 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024508
24509 if ((ctxt == NULL) || (filename == NULL))
24510 return (-1);
24511
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024512 input = xmlParserInputBufferCreateFilename(filename,
24513 XML_CHAR_ENCODING_NONE);
24514 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024515 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024516 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24517 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024518 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024519#else
24520 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024521#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024522}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024523
24524#ifdef XML_SCHEMA_READER_ENABLED
Daniel Veillard81562d22005-06-15 13:27:56 +000024525/**
24526 * xmlSchemaValidateReader:
24527 * @ctxt: a schema validation context
24528 * @reader: an XML reader.
24529 *
24530 * Do a schemas validation of the given resource, using the reader.
24531 *
24532 * Returns 0 if the document is valid, a positive error code
24533 * number otherwise and -1 in case of an internal or API error.
24534 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024535int
24536xmlSchemaValidateReader(xmlSchemaValidCtxtPtr ctxt,
24537 xmlTextReaderPtr reader)
24538{
24539 if ((ctxt == NULL) || (reader == NULL))
24540 return (-1);
24541 ctxt->reader = reader;
24542 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24543 return(xmlSchemaVStart(ctxt, NULL));
24544}
24545#endif /* XML_SCHEMA_READER_ENABLED */
24546
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024547#define bottom_xmlschemas
24548#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024549#endif /* LIBXML_SCHEMAS_ENABLED */