blob: cbd4ed7e511d0275b61cf9f20576f274e6b74e6c [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000069#define DUMP_CONTENT_MODEL
70
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000071#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000104 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000105static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000107#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000108static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000109 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000110#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111
Daniel Veillard4255d502002-04-16 15:50:10 +0000112#define IS_SCHEMA(node, type) \
113 ((node != NULL) && (node->ns != NULL) && \
114 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
115 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
116
Daniel Veillardc0826a72004-08-10 14:17:33 +0000117#define FREE_AND_NULL(str) \
118 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000119 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120 str = NULL; \
121 }
122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000123#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000124 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
125 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000126
127#define IS_COMPLEX_TYPE(item) \
128 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
129 (item->builtInType == XML_SCHEMAS_ANYTYPE))
130
131#define IS_SIMPLE_TYPE(item) \
132 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
133 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000134 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000136#define IS_ANY_SIMPLE_TYPE(item) \
137 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000138 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000139
140#define IS_NOT_TYPEFIXED(item) \
141 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
142 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
143
144#define HAS_COMPLEX_CONTENT(item) \
145 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
146 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
147 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
148
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000149#define HAS_SIMPLE_CONTENT(item) \
150 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
151 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
152
153#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
154
155#define IS_PARTICLE_EMPTIABLE(item) \
156 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000158#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000160#define GET_LIST_ITEM_TYPE(item) item->subtypes
161
162#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
163#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
164#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000166#define IS_MODEL_GROUP(item) \
167 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
168 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
169 (item->type == XML_SCHEMA_TYPE_ALL))
170
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000171#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
172
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000173#define ELEM_TYPE(item) item->subtypes
174
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000175#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000177#define SUBST_GROUP_AFF(item) item->refDecl
178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000179#if 0
180#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
181#endif
182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000183#define SUBSET_RESTRICTION 1<<0
184#define SUBSET_EXTENSION 1<<1
185#define SUBSET_SUBSTITUTION 1<<2
186#define SUBSET_LIST 1<<3
187#define SUBSET_UNION 1<<4
188
Daniel Veillard4255d502002-04-16 15:50:10 +0000189#define XML_SCHEMAS_PARSE_ERROR 1
190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000193typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
194typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000199
200typedef struct _xmlSchemaItemList xmlSchemaItemList;
201typedef xmlSchemaItemList *xmlSchemaItemListPtr;
202
203struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000204 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 int nbItems; /* used for dynamic addition of schemata */
206 int sizeItems; /* used for dynamic addition of schemata */
207};
208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000209typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
210typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
211struct _xmlSchemaAbstractCtxt {
212 int type;
213};
214
215#define XML_SCHEMA_CTXT_PARSER 1
216#define XML_SCHEMA_CTXT_VALIDATOR 2
217
Daniel Veillard4255d502002-04-16 15:50:10 +0000218struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000219 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 void *userData; /* user specific data block */
221 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
222 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000223 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000227 xmlSchemaPtr topschema; /* The main schema */
228 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000231 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 int counter;
233
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000234 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000236 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 const char *buffer;
239 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241 /*
242 * Used to build complex element content models
243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245 xmlAutomataStatePtr start;
246 xmlAutomataStatePtr end;
247 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000248
249 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000250 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000251 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
252 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 xmlSchemaAssemblePtr assemble;
254 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000256 const xmlChar **localImports; /* list of locally imported namespaces */
257 int sizeLocalImports;
258 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000259 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000260 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000261};
262
Daniel Veillard4255d502002-04-16 15:50:10 +0000263#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000267#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
269#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000270#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000271#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
273#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
274#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
275#define XML_SCHEMAS_ATTR_WILD_SKIP 13
276#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
277#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
278#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
279#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281/**
282 * xmlSchemaBasicItem:
283 *
284 * The abstract base type for schema components.
285 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000286typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
287typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
288struct _xmlSchemaBasicItem {
289 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000290};
291
292/**
293 * xmlSchemaAnnotItem:
294 *
295 * The abstract base type for annotated schema components.
296 * (Extends xmlSchemaBasicItem)
297 */
298typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
299typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
300struct _xmlSchemaAnnotItem {
301 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000302 xmlSchemaAnnotPtr annot;
303};
304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000305/**
306 * xmlSchemaTreeItem:
307 *
308 * The abstract base type for tree-like structured schema components.
309 * (Extends xmlSchemaAnnotItem)
310 */
311typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
312typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
313struct _xmlSchemaTreeItem {
314 xmlSchemaTypeType type;
315 xmlSchemaAnnotPtr annot;
316 xmlSchemaTreeItemPtr next;
317 xmlSchemaTreeItemPtr children;
318};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000320/**
321 * xmlSchemaQNameRef:
322 *
323 * A component reference item (not a schema component)
324 * (Extends xmlSchemaBasicItem)
325 */
326typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
327typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
328struct _xmlSchemaQNameRef {
329 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000331 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000332 const xmlChar *name;
333 const xmlChar *targetNamespace;
334};
335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000336/**
337 * xmlSchemaParticle:
338 *
339 * A particle component.
340 * (Extends xmlSchemaTreeItem)
341 */
342typedef struct _xmlSchemaParticle xmlSchemaParticle;
343typedef xmlSchemaParticle *xmlSchemaParticlePtr;
344struct _xmlSchemaParticle {
345 xmlSchemaTypeType type;
346 xmlSchemaAnnotPtr annot;
347 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
348 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
349 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000350 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351 xmlNodePtr node;
352};
353
354/**
355 * xmlSchemaModelGroup:
356 *
357 * A model group component.
358 * (Extends xmlSchemaTreeItem)
359 */
360typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next; /* not used */
366 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
367 xmlNodePtr node;
368};
369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000370#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000371/**
372 * xmlSchemaModelGroupDef:
373 *
374 * A model group definition component.
375 * (Extends xmlSchemaTreeItem)
376 */
377typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
378typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
379struct _xmlSchemaModelGroupDef {
380 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
381 xmlSchemaAnnotPtr annot;
382 xmlSchemaTreeItemPtr next; /* not used */
383 xmlSchemaTreeItemPtr children; /* the "model group" */
384 const xmlChar *name;
385 const xmlChar *targetNamespace;
386 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000387 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388};
389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390typedef struct _xmlSchemaIDC xmlSchemaIDC;
391typedef xmlSchemaIDC *xmlSchemaIDCPtr;
392
393/**
394 * xmlSchemaIDCSelect:
395 *
396 * The identity-constraint "field" and "selector" item, holding the
397 * XPath expression.
398 */
399typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
400typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000401struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402 xmlSchemaIDCSelectPtr next;
403 xmlSchemaIDCPtr idc;
404 int index; /* an index position if significant for IDC key-sequences */
405 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000406 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000407};
408
409/**
410 * xmlSchemaIDC:
411 *
412 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000413 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000414 */
415
416struct _xmlSchemaIDC {
417 xmlSchemaTypeType type;
418 xmlSchemaAnnotPtr annot;
419 xmlSchemaIDCPtr next;
420 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 const xmlChar *targetNamespace;
423 xmlSchemaIDCSelectPtr selector;
424 xmlSchemaIDCSelectPtr fields;
425 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000426 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000427};
428
429/**
430 * xmlSchemaIDCAug:
431 *
432 * The augmented IDC information used for validation.
433 */
434typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
435typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
436struct _xmlSchemaIDCAug {
437 xmlSchemaIDCAugPtr next; /* next in a list */
438 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000439 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000440 tables need to be bubbled upwards */
441};
442
443/**
444 * xmlSchemaPSVIIDCKeySequence:
445 *
446 * The key sequence of a node table item.
447 */
448typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
449typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
450struct _xmlSchemaPSVIIDCKey {
451 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000452 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453};
454
455/**
456 * xmlSchemaPSVIIDCNode:
457 *
458 * The node table item of a node table.
459 */
460typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
461typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
462struct _xmlSchemaPSVIIDCNode {
463 xmlNodePtr node;
464 xmlSchemaPSVIIDCKeyPtr *keys;
465};
466
467/**
468 * xmlSchemaPSVIIDCBinding:
469 *
470 * The identity-constraint binding item of the [identity-constraint table].
471 */
472typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
473typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
474struct _xmlSchemaPSVIIDCBinding {
475 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
476 xmlSchemaIDCPtr definition; /* the IDC definition */
477 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
478 int nbNodes; /* number of entries in the node table */
479 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000480 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 table */
482 /* int nbKeys; number of keys in each key-sequence */
483};
484
485#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
486#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
487
488#define XPATH_STATE_OBJ_MATCHES -2
489#define XPATH_STATE_OBJ_BLOCKED -3
490
491typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
492typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
493
494/**
495 * xmlSchemaIDCStateObj:
496 *
497 * The state object used to evaluate XPath expressions.
498 */
499typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
500typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
501struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000502 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000504 int depth; /* depth of creation */
505 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 int nbHistory;
507 int sizeHistory;
508 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
509 matcher */
510 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000511 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000512};
513
514#define IDC_MATCHER 0
515
516/**
517 * xmlSchemaIDCMatcher:
518 *
519 * Used to IDC selectors (and fields) successively.
520 */
521struct _xmlSchemaIDCMatcher {
522 int type;
523 int depth; /* the tree depth at creation time */
524 xmlSchemaIDCMatcherPtr next; /* next in the list */
525 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
526 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
527 elements */
528 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 int targetDepth;
530};
531
532/*
533* Element info flags.
534*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
536#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
537#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
538#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
539
540#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
541#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
542#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
543
544#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
545#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
546#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
547#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548
549/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000550 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 *
552 * Holds information of an element node.
553 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000554struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000557 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 const xmlChar *nsName;
559 const xmlChar *value;
560 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000562 int flags; /* combination of node info flags */
563 int valNeeded;
564 int normVal;
565
566 xmlSchemaElementPtr decl; /* the element/attribute declaration */
567 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
569 for the scope element*/
570 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
571 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000572 xmlRegExecCtxtPtr regexCtxt;
573
574 const xmlChar **nsBindings; /* Namespace bindings on this element */
575 int nbNsBindings;
576 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000577};
578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000579/*
580* @metaType values of xmlSchemaAttrInfo.
581*/
582#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
584#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
585#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
586#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
589typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
590struct _xmlSchemaAttrInfo {
591 xmlNodePtr node;
592 int nodeType;
593 const xmlChar *localName;
594 const xmlChar *nsName;
595 const xmlChar *value;
596 xmlSchemaValPtr val; /* the pre-computed value if any */
597 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
598 int flags; /* combination of node info flags */
599
600 xmlSchemaAttributePtr decl; /* the attribute declaration */
601 xmlSchemaAttributePtr use; /* the attribute use */
602 int state;
603 int metaType;
604 const xmlChar *vcValue; /* the value constraint value */
605 xmlSchemaNodeInfoPtr parent;
606};
607
608
609#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000610/**
611 * xmlSchemaValidCtxt:
612 *
613 * A Schemas validation context
614 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000615struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *userData; /* user specific data block */
618 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000619 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000621
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 xmlSchemaPtr schema; /* The schema in use */
623 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 xmlCharEncoding enc;
626 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000627 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000629
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 int err;
631 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000632
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000633 xmlNodePtr node;
634 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000635 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637 xmlRegExecCtxtPtr regexp;
638 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000639
Daniel Veillardc0826a72004-08-10 14:17:33 +0000640 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000641 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000642 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000643 xmlSchemaParserCtxtPtr pctxt;
644 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000647 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000649 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
652
653 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
654 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000655
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
657 int nbIdcNodes;
658 int sizeIdcNodes;
659
660 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
661 int nbIdcKeys;
662 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000663
664 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000665
666 xmlDictPtr dict;
667
Daniel Veillard39e5c892005-07-03 22:48:50 +0000668#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000670#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671
672 xmlSchemaAttrInfoPtr *attrInfos;
673 int nbAttrInfos;
674 int sizeAttrInfos;
675
676 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000677};
678
Daniel Veillard1d913862003-11-21 00:28:39 +0000679/*
680 * These are the entries in the schemas importSchemas hash table
681 */
682typedef struct _xmlSchemaImport xmlSchemaImport;
683typedef xmlSchemaImport *xmlSchemaImportPtr;
684struct _xmlSchemaImport {
685 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000686 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000687 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000688 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000689};
Daniel Veillard4255d502002-04-16 15:50:10 +0000690
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000691/*
692 * These are the entries associated to includes in a schemas
693 */
694typedef struct _xmlSchemaInclude xmlSchemaInclude;
695typedef xmlSchemaInclude *xmlSchemaIncludePtr;
696struct _xmlSchemaInclude {
697 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698 const xmlChar *schemaLocation;
699 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000700 const xmlChar *origTargetNamespace;
701 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000702};
703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000704/**
705 * xmlSchemaSubstGroup:
706 *
707 *
708 */
709typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
710typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
711struct _xmlSchemaSubstGroup {
712 xmlSchemaElementPtr head;
713 xmlSchemaItemListPtr members;
714};
715
Daniel Veillard4255d502002-04-16 15:50:10 +0000716/************************************************************************
717 * *
718 * Some predeclarations *
719 * *
720 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000722static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
723 xmlSchemaPtr schema,
724 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725static void
726xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
727 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000728static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000729xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
730static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000731xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
732 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000733static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000734xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
735 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000736static void
737xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000738static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000739xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740static xmlSchemaTreeItemPtr
741xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
742 xmlNodePtr node, xmlSchemaTypeType type,
743 int withParticle);
744static const xmlChar *
745xmlSchemaCompTypeToString(xmlSchemaTypeType type);
746static xmlSchemaTypeLinkPtr
747xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748static void
749xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
750 const char *funcName,
751 const char *message);
752static int
753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
754 xmlSchemaTypePtr baseType,
755 int subset);
756static void
757xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
758 xmlSchemaParserCtxtPtr ctxt,
759 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000760
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761/************************************************************************
762 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000763 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 * *
765 ************************************************************************/
766
767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000768 * xmlSchemaCompTypeToString:
769 * @type: the type of the schema item
770 *
771 * Returns the component name of a schema item.
772 */
773static const xmlChar *
774xmlSchemaCompTypeToString(xmlSchemaTypeType type)
775{
776 switch (type) {
777 case XML_SCHEMA_TYPE_SIMPLE:
778 return(BAD_CAST "simple type definition");
779 case XML_SCHEMA_TYPE_COMPLEX:
780 return(BAD_CAST "complex type definition");
781 case XML_SCHEMA_TYPE_ELEMENT:
782 return(BAD_CAST "element declaration");
783 case XML_SCHEMA_TYPE_ATTRIBUTE:
784 return(BAD_CAST "attribute declaration");
785 case XML_SCHEMA_TYPE_GROUP:
786 return(BAD_CAST "model group definition");
787 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
788 return(BAD_CAST "attribute group definition");
789 case XML_SCHEMA_TYPE_NOTATION:
790 return(BAD_CAST "notation declaration");
791 case XML_SCHEMA_TYPE_SEQUENCE:
792 return(BAD_CAST "model group (sequence)");
793 case XML_SCHEMA_TYPE_CHOICE:
794 return(BAD_CAST "model group (choice)");
795 case XML_SCHEMA_TYPE_ALL:
796 return(BAD_CAST "model group (all)");
797 case XML_SCHEMA_TYPE_PARTICLE:
798 return(BAD_CAST "particle");
799 default:
800 return(BAD_CAST "Not a schema component");
801 }
802}
803
804/**
805 * xmlSchemaGetComponentNode:
806 * @item: a schema component
807 *
808 * Returns node associated with the schema component.
809 * NOTE that such a node need not be available; plus, a component's
810 * node need not to reflect the component directly, since there is no
811 * one-to-one relationship between the XML Schema representation and
812 * the component representation.
813 */
814static xmlNodePtr
815xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
816{
817 switch (item->type) {
818 case XML_SCHEMA_TYPE_ELEMENT:
819 return (((xmlSchemaElementPtr) item)->node);
820 case XML_SCHEMA_TYPE_ATTRIBUTE:
821 return (((xmlSchemaAttributePtr) item)->node);
822 case XML_SCHEMA_TYPE_COMPLEX:
823 case XML_SCHEMA_TYPE_SIMPLE:
824 return (((xmlSchemaTypePtr) item)->node);
825 case XML_SCHEMA_TYPE_ANY:
826 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
827 return (((xmlSchemaWildcardPtr) item)->node);
828 case XML_SCHEMA_TYPE_PARTICLE:
829 return (((xmlSchemaParticlePtr) item)->node);
830 case XML_SCHEMA_TYPE_SEQUENCE:
831 case XML_SCHEMA_TYPE_CHOICE:
832 case XML_SCHEMA_TYPE_ALL:
833 return (((xmlSchemaModelGroupPtr) item)->node);
834 case XML_SCHEMA_TYPE_GROUP:
835 return (((xmlSchemaModelGroupDefPtr) item)->node);
836 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
837 return (((xmlSchemaAttributeGroupPtr) item)->node);
838 case XML_SCHEMA_TYPE_IDC_UNIQUE:
839 case XML_SCHEMA_TYPE_IDC_KEY:
840 case XML_SCHEMA_TYPE_IDC_KEYREF:
841 return (((xmlSchemaIDCPtr) item)->node);
842 default:
843 return (NULL);
844 }
845}
846
847#if 0
848/**
849 * xmlSchemaGetNextComponent:
850 * @item: a schema component
851 *
852 * Returns the next sibling of the schema component.
853 */
854static xmlSchemaBasicItemPtr
855xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
856{
857 switch (item->type) {
858 case XML_SCHEMA_TYPE_ELEMENT:
859 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
860 case XML_SCHEMA_TYPE_ATTRIBUTE:
861 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
862 case XML_SCHEMA_TYPE_COMPLEX:
863 case XML_SCHEMA_TYPE_SIMPLE:
864 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
865 case XML_SCHEMA_TYPE_ANY:
866 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
867 return (NULL);
868 case XML_SCHEMA_TYPE_PARTICLE:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
870 case XML_SCHEMA_TYPE_SEQUENCE:
871 case XML_SCHEMA_TYPE_CHOICE:
872 case XML_SCHEMA_TYPE_ALL:
873 return (NULL);
874 case XML_SCHEMA_TYPE_GROUP:
875 return (NULL);
876 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
877 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
878 case XML_SCHEMA_TYPE_IDC_UNIQUE:
879 case XML_SCHEMA_TYPE_IDC_KEY:
880 case XML_SCHEMA_TYPE_IDC_KEYREF:
881 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
882 default:
883 return (NULL);
884 }
885}
886#endif
887
888/**
889 * xmlSchemaGetAttrName:
890 * @attr: the attribute declaration/use
891 *
892 * Returns the name of the attribute; if the attribute
893 * is a reference, the name of the referenced global type will be returned.
894 */
895static const xmlChar *
896xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
897{
898 if (attr->ref != NULL)
899 return(attr->ref);
900 else
901 return(attr->name);
902}
903
904/**
905 * xmlSchemaGetAttrTargetNsURI:
906 * @type: the type (element or attribute)
907 *
908 * Returns the target namespace URI of the type; if the type is a reference,
909 * the target namespace of the referenced type will be returned.
910 */
911static const xmlChar *
912xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
913{
914 if (attr->ref != NULL)
915 return (attr->refNs);
916 else
917 return(attr->targetNamespace);
918}
919
920/**
921 * xmlSchemaFormatQName:
922 * @buf: the string buffer
923 * @namespaceName: the namespace name
924 * @localName: the local name
925 *
926 * Returns the given QName in the format "{namespaceName}localName" or
927 * just "localName" if @namespaceName is NULL.
928 *
929 * Returns the localName if @namespaceName is NULL, a formatted
930 * string otherwise.
931 */
932static const xmlChar*
933xmlSchemaFormatQName(xmlChar **buf,
934 const xmlChar *namespaceName,
935 const xmlChar *localName)
936{
937 FREE_AND_NULL(*buf)
938 if (namespaceName == NULL)
939 return(localName);
940
941 *buf = xmlStrdup(BAD_CAST "{");
942 *buf = xmlStrcat(*buf, namespaceName);
943 *buf = xmlStrcat(*buf, BAD_CAST "}");
944 *buf = xmlStrcat(*buf, localName);
945
946 return ((const xmlChar *) *buf);
947}
948
949static const xmlChar*
950xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
951{
952 if (ns != NULL)
953 return (xmlSchemaFormatQName(buf, ns->href, localName));
954 else
955 return (xmlSchemaFormatQName(buf, NULL, localName));
956}
957
958static const xmlChar *
959xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
960{
961 switch (item->type) {
962 case XML_SCHEMA_TYPE_ELEMENT:
963 return (((xmlSchemaElementPtr) item)->name);
964 case XML_SCHEMA_TYPE_ATTRIBUTE:
965 return (((xmlSchemaAttributePtr) item)->name);
966 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
967 return (((xmlSchemaAttributeGroupPtr) item)->name);
968 case XML_SCHEMA_TYPE_BASIC:
969 case XML_SCHEMA_TYPE_SIMPLE:
970 case XML_SCHEMA_TYPE_COMPLEX:
971 return (((xmlSchemaTypePtr) item)->name);
972 case XML_SCHEMA_TYPE_GROUP:
973 return (((xmlSchemaModelGroupDefPtr) item)->name);
974 case XML_SCHEMA_TYPE_IDC_KEY:
975 case XML_SCHEMA_TYPE_IDC_UNIQUE:
976 case XML_SCHEMA_TYPE_IDC_KEYREF:
977 return (((xmlSchemaIDCPtr) item)->name);
978 default:
979 /*
980 * Other components cannot have names.
981 */
982 break;
983 }
984 return (NULL);
985}
986
987static const xmlChar *
988xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
989{
990 switch (item->type) {
991 case XML_SCHEMA_TYPE_ELEMENT:
992 return (((xmlSchemaElementPtr) item)->targetNamespace);
993 case XML_SCHEMA_TYPE_ATTRIBUTE:
994 return (((xmlSchemaAttributePtr) item)->targetNamespace);
995 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
996 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
997 case XML_SCHEMA_TYPE_BASIC:
998 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
999 case XML_SCHEMA_TYPE_SIMPLE:
1000 case XML_SCHEMA_TYPE_COMPLEX:
1001 return (((xmlSchemaTypePtr) item)->targetNamespace);
1002 case XML_SCHEMA_TYPE_GROUP:
1003 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1004 case XML_SCHEMA_TYPE_IDC_KEY:
1005 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1006 case XML_SCHEMA_TYPE_IDC_KEYREF:
1007 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1008 default:
1009 /*
1010 * Other components cannot have names.
1011 */
1012 break;
1013 }
1014 return (NULL);
1015}
1016
1017static const xmlChar*
1018xmlSchemaGetComponentQName(xmlChar **buf,
1019 void *item)
1020{
1021 return (xmlSchemaFormatQName(buf,
1022 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1023 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1024}
1025
1026/**
1027 * xmlSchemaWildcardPCToString:
1028 * @pc: the type of processContents
1029 *
1030 * Returns a string representation of the type of
1031 * processContents.
1032 */
1033static const xmlChar *
1034xmlSchemaWildcardPCToString(int pc)
1035{
1036 switch (pc) {
1037 case XML_SCHEMAS_ANY_SKIP:
1038 return (BAD_CAST "skip");
1039 case XML_SCHEMAS_ANY_LAX:
1040 return (BAD_CAST "lax");
1041 case XML_SCHEMAS_ANY_STRICT:
1042 return (BAD_CAST "strict");
1043 default:
1044 return (BAD_CAST "invalid process contents");
1045 }
1046}
1047
1048/**
1049 * xmlSchemaGetCanonValueWhtspExt:
1050 * @val: the precomputed value
1051 * @retValue: the returned value
1052 * @ws: the whitespace type of the value
1053 *
1054 * Get a the cononical representation of the value.
1055 * The caller has to free the returned retValue.
1056 *
1057 * Returns 0 if the value could be built and -1 in case of
1058 * API errors or if the value type is not supported yet.
1059 */
1060static int
1061xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1062 xmlSchemaWhitespaceValueType ws,
1063 xmlChar **retValue)
1064{
1065 int list;
1066 xmlSchemaValType valType;
1067 const xmlChar *value, *value2 = NULL;
1068
1069
1070 if ((retValue == NULL) || (val == NULL))
1071 return (-1);
1072 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1073 *retValue = NULL;
1074 do {
1075 value = NULL;
1076 valType = xmlSchemaGetValType(val);
1077 switch (valType) {
1078 case XML_SCHEMAS_STRING:
1079 case XML_SCHEMAS_NORMSTRING:
1080 case XML_SCHEMAS_ANYSIMPLETYPE:
1081 value = xmlSchemaValueGetAsString(val);
1082 if (value != NULL) {
1083 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1084 value2 = xmlSchemaCollapseString(value);
1085 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1086 value2 = xmlSchemaWhiteSpaceReplace(value);
1087 if (value2 != NULL)
1088 value = value2;
1089 }
1090 break;
1091 default:
1092 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1093 if (value2 != NULL)
1094 xmlFree((xmlChar *) value2);
1095 goto internal_error;
1096 }
1097 value = value2;
1098 }
1099 if (*retValue == NULL)
1100 if (value == NULL) {
1101 if (! list)
1102 *retValue = xmlStrdup(BAD_CAST "");
1103 } else
1104 *retValue = xmlStrdup(value);
1105 else if (value != NULL) {
1106 /* List. */
1107 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1108 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1109 }
1110 FREE_AND_NULL(value2)
1111 val = xmlSchemaValueGetNext(val);
1112 } while (val != NULL);
1113
1114 return (0);
1115internal_error:
1116 if (*retValue != NULL)
1117 xmlFree((xmlChar *) (*retValue));
1118 if (value2 != NULL)
1119 xmlFree((xmlChar *) value2);
1120 return (-1);
1121}
1122
1123/**
1124 * xmlSchemaFormatItemForReport:
1125 * @buf: the string buffer
1126 * @itemDes: the designation of the item
1127 * @itemName: the name of the item
1128 * @item: the item as an object
1129 * @itemNode: the node of the item
1130 * @local: the local name
1131 * @parsing: if the function is used during the parse
1132 *
1133 * Returns a representation of the given item used
1134 * for error reports.
1135 *
1136 * The following order is used to build the resulting
1137 * designation if the arguments are not NULL:
1138 * 1a. If itemDes not NULL -> itemDes
1139 * 1b. If (itemDes not NULL) and (itemName not NULL)
1140 * -> itemDes + itemName
1141 * 2. If the preceding was NULL and (item not NULL) -> item
1142 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1143 *
1144 * If the itemNode is an attribute node, the name of the attribute
1145 * will be appended to the result.
1146 *
1147 * Returns the formatted string and sets @buf to the resulting value.
1148 */
1149static xmlChar*
1150xmlSchemaFormatItemForReport(xmlChar **buf,
1151 const xmlChar *itemDes,
1152 xmlSchemaTypePtr item,
1153 xmlNodePtr itemNode)
1154{
1155 xmlChar *str = NULL;
1156 int named = 1;
1157
1158 if (*buf != NULL) {
1159 xmlFree(*buf);
1160 *buf = NULL;
1161 }
1162
1163 if (itemDes != NULL) {
1164 *buf = xmlStrdup(itemDes);
1165 } else if (item != NULL) {
1166 switch (item->type) {
1167 case XML_SCHEMA_TYPE_BASIC:
1168 if (VARIETY_ATOMIC(item))
1169 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1170 else if (VARIETY_LIST(item))
1171 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1172 else if (VARIETY_UNION(item))
1173 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1174 else
1175 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1176 *buf = xmlStrcat(*buf, item->name);
1177 *buf = xmlStrcat(*buf, BAD_CAST "'");
1178 break;
1179 case XML_SCHEMA_TYPE_SIMPLE:
1180 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1181 *buf = xmlStrdup(BAD_CAST"");
1182 } else {
1183 *buf = xmlStrdup(BAD_CAST "local ");
1184 }
1185 if (VARIETY_ATOMIC(item))
1186 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1187 else if (VARIETY_LIST(item))
1188 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1189 else if (VARIETY_UNION(item))
1190 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1191 else
1192 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1193 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1194 *buf = xmlStrcat(*buf, BAD_CAST " '");
1195 *buf = xmlStrcat(*buf, item->name);
1196 *buf = xmlStrcat(*buf, BAD_CAST "'");
1197 }
1198 break;
1199 case XML_SCHEMA_TYPE_COMPLEX:
1200 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1201 *buf = xmlStrdup(BAD_CAST "");
1202 else
1203 *buf = xmlStrdup(BAD_CAST "local ");
1204 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1205 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1206 *buf = xmlStrcat(*buf, BAD_CAST " '");
1207 *buf = xmlStrcat(*buf, item->name);
1208 *buf = xmlStrcat(*buf, BAD_CAST "'");
1209 }
1210 break;
1211 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1212 xmlSchemaAttributePtr attr;
1213
1214 attr = (xmlSchemaAttributePtr) item;
1215 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1216 (attr->ref == NULL)) {
1217 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1218 *buf = xmlStrcat(*buf, BAD_CAST " '");
1219 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1220 attr->targetNamespace, attr->name));
1221 FREE_AND_NULL(str)
1222 *buf = xmlStrcat(*buf, BAD_CAST "'");
1223 } else {
1224 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1225 *buf = xmlStrcat(*buf, BAD_CAST " '");
1226 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1227 attr->refNs, attr->ref));
1228 FREE_AND_NULL(str)
1229 *buf = xmlStrcat(*buf, BAD_CAST "'");
1230 }
1231 }
1232 break;
1233 case XML_SCHEMA_TYPE_ELEMENT: {
1234 xmlSchemaElementPtr elem;
1235
1236 elem = (xmlSchemaElementPtr) item;
1237 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1238 (elem->ref == NULL)) {
1239 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1240 *buf = xmlStrcat(*buf, BAD_CAST " '");
1241 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1242 elem->targetNamespace, elem->name));
1243 *buf = xmlStrcat(*buf, BAD_CAST "'");
1244 }
1245 }
1246 break;
1247 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1248 case XML_SCHEMA_TYPE_IDC_KEY:
1249 case XML_SCHEMA_TYPE_IDC_KEYREF:
1250 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1251 *buf = xmlStrdup(BAD_CAST "unique '");
1252 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1253 *buf = xmlStrdup(BAD_CAST "key '");
1254 else
1255 *buf = xmlStrdup(BAD_CAST "keyRef '");
1256 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1257 *buf = xmlStrcat(*buf, BAD_CAST "'");
1258 break;
1259 case XML_SCHEMA_TYPE_ANY:
1260 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1261 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1262 ((xmlSchemaWildcardPtr) item)->processContents));
1263 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1264 break;
1265 case XML_SCHEMA_FACET_MININCLUSIVE:
1266 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1267 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1268 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1269 case XML_SCHEMA_FACET_TOTALDIGITS:
1270 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1271 case XML_SCHEMA_FACET_PATTERN:
1272 case XML_SCHEMA_FACET_ENUMERATION:
1273 case XML_SCHEMA_FACET_WHITESPACE:
1274 case XML_SCHEMA_FACET_LENGTH:
1275 case XML_SCHEMA_FACET_MAXLENGTH:
1276 case XML_SCHEMA_FACET_MINLENGTH:
1277 *buf = xmlStrdup(BAD_CAST "facet '");
1278 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1279 *buf = xmlStrcat(*buf, BAD_CAST "'");
1280 break;
1281 case XML_SCHEMA_TYPE_NOTATION:
1282 *buf = xmlStrdup(BAD_CAST "notation");
1283 break;
1284 case XML_SCHEMA_TYPE_GROUP: {
1285 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1286 *buf = xmlStrcat(*buf, BAD_CAST " '");
1287 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1288 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1289 ((xmlSchemaModelGroupDefPtr) item)->name));
1290 *buf = xmlStrcat(*buf, BAD_CAST "'");
1291 FREE_AND_NULL(str)
1292 }
1293 break;
1294 case XML_SCHEMA_TYPE_SEQUENCE:
1295 case XML_SCHEMA_TYPE_CHOICE:
1296 case XML_SCHEMA_TYPE_ALL:
1297 case XML_SCHEMA_TYPE_PARTICLE:
1298 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1299 break;
1300 default:
1301 named = 0;
1302 }
1303 } else
1304 named = 0;
1305
1306 if ((named == 0) && (itemNode != NULL)) {
1307 xmlNodePtr elem;
1308
1309 if (itemNode->type == XML_ATTRIBUTE_NODE)
1310 elem = itemNode->parent;
1311 else
1312 elem = itemNode;
1313 *buf = xmlStrdup(BAD_CAST "Element '");
1314 if (elem->ns != NULL) {
1315 *buf = xmlStrcat(*buf,
1316 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1317 FREE_AND_NULL(str)
1318 } else
1319 *buf = xmlStrcat(*buf, elem->name);
1320 *buf = xmlStrcat(*buf, BAD_CAST "'");
1321
1322 }
1323 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1324 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1325 if (itemNode->ns != NULL) {
1326 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1327 itemNode->ns->href, itemNode->name));
1328 FREE_AND_NULL(str)
1329 } else
1330 *buf = xmlStrcat(*buf, itemNode->name);
1331 *buf = xmlStrcat(*buf, BAD_CAST "'");
1332 }
1333 FREE_AND_NULL(str)
1334
1335 return (*buf);
1336}
1337
1338/**
1339 * xmlSchemaFormatFacetEnumSet:
1340 * @buf: the string buffer
1341 * @type: the type holding the enumeration facets
1342 *
1343 * Builds a string consisting of all enumeration elements.
1344 *
1345 * Returns a string of all enumeration elements.
1346 */
1347static const xmlChar *
1348xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1349 xmlChar **buf, xmlSchemaTypePtr type)
1350{
1351 xmlSchemaFacetPtr facet;
1352 xmlSchemaWhitespaceValueType ws;
1353 xmlChar *value = NULL;
1354 int res;
1355
1356 if (*buf != NULL)
1357 xmlFree(*buf);
1358 *buf = NULL;
1359
1360 do {
1361 /*
1362 * Use the whitespace type of the base type.
1363 */
1364 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1365 for (facet = type->facets; facet != NULL; facet = facet->next) {
1366 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1367 continue;
1368 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1369 ws, &value);
1370 if (res == -1) {
1371 xmlSchemaInternalErr(actxt,
1372 "xmlSchemaFormatFacetEnumSet",
1373 "compute the canonical lexical representation");
1374 if (*buf != NULL)
1375 xmlFree(*buf);
1376 *buf = NULL;
1377 return (NULL);
1378 }
1379 if (*buf == NULL)
1380 *buf = xmlStrdup(BAD_CAST "'");
1381 else
1382 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1383 *buf = xmlStrcat(*buf, BAD_CAST value);
1384 *buf = xmlStrcat(*buf, BAD_CAST "'");
1385 if (value != NULL) {
1386 xmlFree((xmlChar *)value);
1387 value = NULL;
1388 }
1389 }
1390 type = type->baseType;
1391 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1392
1393 return ((const xmlChar *) *buf);
1394}
1395
1396/************************************************************************
1397 * *
1398 * Error functions *
1399 * *
1400 ************************************************************************/
1401
1402#if 0
1403static void
1404xmlSchemaErrMemory(const char *msg)
1405{
1406 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1407 msg);
1408}
1409#endif
1410
1411/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001412 * xmlSchemaPErrMemory:
1413 * @node: a context node
1414 * @extra: extra informations
1415 *
1416 * Handle an out of memory condition
1417 */
1418static void
1419xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1420 const char *extra, xmlNodePtr node)
1421{
1422 if (ctxt != NULL)
1423 ctxt->nberrors++;
1424 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1425 extra);
1426}
1427
1428/**
1429 * xmlSchemaPErr:
1430 * @ctxt: the parsing context
1431 * @node: the context node
1432 * @error: the error code
1433 * @msg: the error message
1434 * @str1: extra data
1435 * @str2: extra data
1436 *
1437 * Handle a parser error
1438 */
1439static void
1440xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1441 const char *msg, const xmlChar * str1, const xmlChar * str2)
1442{
1443 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001444 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001445 void *data = NULL;
1446
1447 if (ctxt != NULL) {
1448 ctxt->nberrors++;
1449 channel = ctxt->error;
1450 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001451 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001453 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 error, XML_ERR_ERROR, NULL, 0,
1455 (const char *) str1, (const char *) str2, NULL, 0, 0,
1456 msg, str1, str2);
1457}
1458
1459/**
1460 * xmlSchemaPErr2:
1461 * @ctxt: the parsing context
1462 * @node: the context node
1463 * @node: the current child
1464 * @error: the error code
1465 * @msg: the error message
1466 * @str1: extra data
1467 * @str2: extra data
1468 *
1469 * Handle a parser error
1470 */
1471static void
1472xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1473 xmlNodePtr child, int error,
1474 const char *msg, const xmlChar * str1, const xmlChar * str2)
1475{
1476 if (child != NULL)
1477 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1478 else
1479 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1480}
1481
Daniel Veillard01fa6152004-06-29 17:04:39 +00001482
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001483/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001484 * xmlSchemaPErrExt:
1485 * @ctxt: the parsing context
1486 * @node: the context node
1487 * @error: the error code
1488 * @strData1: extra data
1489 * @strData2: extra data
1490 * @strData3: extra data
1491 * @msg: the message
1492 * @str1: extra parameter for the message display
1493 * @str2: extra parameter for the message display
1494 * @str3: extra parameter for the message display
1495 * @str4: extra parameter for the message display
1496 * @str5: extra parameter for the message display
1497 *
1498 * Handle a parser error
1499 */
1500static void
1501xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1502 const xmlChar * strData1, const xmlChar * strData2,
1503 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1504 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1505 const xmlChar * str5)
1506{
1507
1508 xmlGenericErrorFunc channel = NULL;
1509 xmlStructuredErrorFunc schannel = NULL;
1510 void *data = NULL;
1511
1512 if (ctxt != NULL) {
1513 ctxt->nberrors++;
1514 channel = ctxt->error;
1515 data = ctxt->userData;
1516 schannel = ctxt->serror;
1517 }
1518 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1519 error, XML_ERR_ERROR, NULL, 0,
1520 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001521 (const char *) strData3, 0, 0, msg, str1, str2,
1522 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001523}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001525/************************************************************************
1526 * *
1527 * Allround error functions *
1528 * *
1529 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001530
1531/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001532 * xmlSchemaVTypeErrMemory:
1533 * @node: a context node
1534 * @extra: extra informations
1535 *
1536 * Handle an out of memory condition
1537 */
1538static void
1539xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1540 const char *extra, xmlNodePtr node)
1541{
1542 if (ctxt != NULL) {
1543 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001544 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001545 }
1546 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1547 extra);
1548}
1549
1550/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001551 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 * @ctxt: the validation context
1553 * @node: the context node
1554 * @error: the error code
1555 * @msg: the error message
1556 * @str1: extra data
1557 * @str2: extra data
1558 * @str3: extra data
1559 *
1560 * Handle a validation error
1561 */
1562static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001563xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1564 int error, xmlNodePtr node, const char *msg,
1565 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001566{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001567 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001568 xmlGenericErrorFunc channel = NULL;
1569 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571 if (ctxt != NULL) {
1572 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1573 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001574 int line = 0;
1575 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001576
1577 vctxt->nberrors++;
1578 vctxt->err = error;
1579 channel = vctxt->error;
1580 schannel = vctxt->serror;
1581 data = vctxt->userData;
1582 if ((node == NULL) && (vctxt->depth >= 0) &&
Daniel Veillard971771e2005-07-09 17:32:57 +00001583 (vctxt->inode != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001584 node = vctxt->inode->node;
Daniel Veillard971771e2005-07-09 17:32:57 +00001585 }
1586 if ((node == NULL) && (vctxt->parserCtxt != NULL) &&
1587 (vctxt->parserCtxt->input != NULL)) {
1588 file = vctxt->parserCtxt->input->filename;
1589 line = vctxt->parserCtxt->input->line;
1590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001591 __xmlRaiseError(schannel, channel, data, ctxt,
1592 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001593 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001594 (const char *) str1, (const char *) str2,
1595 (const char *) str3, 0, 0, msg, str1, str2, str3);
1596
1597 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1598 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1599
1600 pctxt->nberrors++;
1601 pctxt->err = error;
1602 channel = pctxt->error;
1603 schannel = pctxt->serror;
1604 data = pctxt->userData;
1605 __xmlRaiseError(schannel, channel, data, ctxt,
1606 node, XML_FROM_SCHEMASP,
1607 error, XML_ERR_ERROR, NULL, 0,
1608 (const char *) str1, (const char *) str2,
1609 (const char *) str3, 0, 0, msg, str1, str2, str3);
1610 } else {
1611 TODO
1612 }
1613 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001614}
1615
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001616static void
1617xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1618 int error, xmlNodePtr node, const char *msg,
1619 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001620{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001621 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001622}
1623
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001624static xmlChar *
1625xmlSchemaFormatNodeForError(xmlChar ** msg,
1626 xmlSchemaAbstractCtxtPtr actxt,
1627 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001628{
1629 xmlChar *str = NULL;
1630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001631 if (node != NULL) {
1632 /*
1633 * Work on tree nodes.
1634 */
1635 if (node->type == XML_ATTRIBUTE_NODE) {
1636 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001637
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001638 *msg = xmlStrdup(BAD_CAST "Element '");
1639 if (elem->ns != NULL)
1640 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1641 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001642 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001643 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1644 NULL, elem->name));
1645 FREE_AND_NULL(str);
1646 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1647 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1648 } else {
1649 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001650 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001651 if (node->ns != NULL)
1652 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1653 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001654 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001655 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1656 NULL, node->name));
1657 FREE_AND_NULL(str);
1658 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1659 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1660 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1661 /*
1662 * Work on node infos.
1663 */
1664 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1665 xmlSchemaNodeInfoPtr ielem =
1666 vctxt->elemInfos[vctxt->depth];
1667
1668 *msg = xmlStrdup(BAD_CAST "Element '");
1669 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1670 ielem->nsName, ielem->localName));
1671 FREE_AND_NULL(str);
1672 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1673 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1674 } else {
1675 *msg = xmlStrdup(BAD_CAST "Element '");
1676 }
1677 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1678 vctxt->inode->nsName, vctxt->inode->localName));
1679 FREE_AND_NULL(str);
1680 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1681 } else {
1682 TODO
1683 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001684 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001685 /*
1686 * VAL TODO: The output of the given schema component is currently
1687 * disabled.
1688 */
1689#if 0
1690 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1691 *msg = xmlStrcat(*msg, BAD_CAST " [");
1692 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1693 NULL, type, NULL, 0));
1694 FREE_AND_NULL(str)
1695 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001697#endif
1698 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001699}
1700
Daniel Veillardc0826a72004-08-10 14:17:33 +00001701static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001702xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1703 const char *funcName,
1704 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001705{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001706 xmlChar *msg = NULL;
1707
1708 msg = xmlStrdup(BAD_CAST "Internal error: ");
1709 msg = xmlStrcat(msg, BAD_CAST funcName);
1710 msg = xmlStrcat(msg, BAD_CAST ", ");
1711 msg = xmlStrcat(msg, BAD_CAST message);
1712 msg = xmlStrcat(msg, BAD_CAST ".\n");
1713
1714 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1715 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1716 (const char *) msg, NULL, NULL);
1717
1718 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1719 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1720 (const char *) msg, NULL, NULL);
1721
1722 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001723}
1724
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001725static void
1726xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1727 xmlParserErrors error,
1728 xmlNodePtr node,
1729 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1730 const char *message,
1731 const xmlChar *str1,
1732 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001733{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001734 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001735
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001736 xmlSchemaFormatNodeForError(&msg, actxt, node);
1737 msg = xmlStrcat(msg, (const xmlChar *) message);
1738 msg = xmlStrcat(msg, BAD_CAST ".\n");
1739 xmlSchemaErr(actxt, error, node,
1740 (const char *) msg, str1, str2);
1741 FREE_AND_NULL(msg)
1742}
1743
1744static int
1745xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1746 xmlNodePtr node)
1747{
1748 if (node != NULL)
1749 return (node->type);
1750 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1751 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1752 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1753 return (-1);
1754}
1755
1756static int
1757xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1758{
1759 switch (item->type) {
1760 case XML_SCHEMA_TYPE_COMPLEX:
1761 case XML_SCHEMA_TYPE_SIMPLE:
1762 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1763 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001764 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001765 case XML_SCHEMA_TYPE_GROUP:
1766 return (1);
1767 case XML_SCHEMA_TYPE_ELEMENT:
1768 if ( ((xmlSchemaElementPtr) item)->flags &
1769 XML_SCHEMAS_ELEM_GLOBAL)
1770 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001771 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001772 case XML_SCHEMA_TYPE_ATTRIBUTE:
1773 if ( ((xmlSchemaAttributePtr) item)->flags &
1774 XML_SCHEMAS_ATTR_GLOBAL)
1775 return(1);
1776 break;
1777 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001778 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001779 return(1);
1780 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001781 return (0);
1782}
1783
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001784static void
1785xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1786 xmlParserErrors error,
1787 xmlNodePtr node,
1788 const xmlChar *value,
1789 xmlSchemaTypePtr type,
1790 int displayValue)
1791{
1792 xmlChar *msg = NULL;
1793
1794 xmlSchemaFormatNodeForError(&msg, actxt, node);
1795
1796 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1797 XML_ATTRIBUTE_NODE))
1798 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1799 else
1800 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1801 "value of ");
1802
1803 if (! xmlSchemaIsGlobalItem(type))
1804 msg = xmlStrcat(msg, BAD_CAST "the local ");
1805 else
1806 msg = xmlStrcat(msg, BAD_CAST "the ");
1807
1808 if (VARIETY_ATOMIC(type))
1809 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1810 else if (VARIETY_LIST(type))
1811 msg = xmlStrcat(msg, BAD_CAST "list type");
1812 else if (VARIETY_UNION(type))
1813 msg = xmlStrcat(msg, BAD_CAST "union type");
1814
1815 if (xmlSchemaIsGlobalItem(type)) {
1816 xmlChar *str = NULL;
1817 msg = xmlStrcat(msg, BAD_CAST " '");
1818 if (type->builtInType != 0) {
1819 msg = xmlStrcat(msg, BAD_CAST "xs:");
1820 msg = xmlStrcat(msg, type->name);
1821 } else
1822 msg = xmlStrcat(msg,
1823 xmlSchemaFormatQName(&str,
1824 type->targetNamespace, type->name));
1825 msg = xmlStrcat(msg, BAD_CAST "'");
1826 FREE_AND_NULL(str);
1827 }
1828 msg = xmlStrcat(msg, BAD_CAST ".\n");
1829 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1830 XML_ATTRIBUTE_NODE))
1831 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1832 else
1833 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1834 FREE_AND_NULL(msg)
1835}
1836
Daniel Veillardc0826a72004-08-10 14:17:33 +00001837static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001838xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1839 xmlSchemaNodeInfoPtr ni,
1840 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001841{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001842 if (node != NULL) {
1843 if (node->ns != NULL)
1844 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1845 else
1846 return (xmlSchemaFormatQName(str, NULL, node->name));
1847 } else if (ni != NULL)
1848 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1849 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001850}
1851
Daniel Veillardc0826a72004-08-10 14:17:33 +00001852static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001853xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1854 xmlParserErrors error,
1855 xmlSchemaAttrInfoPtr ni,
1856 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001857{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001858 xmlChar *msg = NULL, *str = NULL;
1859
1860 xmlSchemaFormatNodeForError(&msg, actxt, node);
1861 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1862 xmlSchemaErr(actxt, error, node, (const char *) msg,
1863 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1864 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001865 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001866 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001867}
1868
Daniel Veillardc0826a72004-08-10 14:17:33 +00001869static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001870xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1871 xmlParserErrors error,
1872 xmlNodePtr node,
1873 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001874 const char *message,
1875 int nbval,
1876 int nbneg,
1877 xmlChar **values)
1878{
1879 xmlChar *str = NULL, *msg = NULL;
1880 xmlChar *localName, *nsName;
1881 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00001882 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001883
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001884 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001885 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001886 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001887 /*
1888 * Note that is does not make sense to report that we have a
1889 * wildcard here, since the wildcard might be unfolded into
1890 * multiple transitions.
1891 */
1892 if (nbval + nbneg > 0) {
1893 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001894 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001895 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001896 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001897 nsName = NULL;
1898
1899 for (i = 0; i < nbval + nbneg; i++) {
1900 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00001901 if (cur == NULL)
1902 continue;
1903 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
1904 (cur[3] == ' ')) {
1905 is_not = 1;
1906 cur += 4;
1907 str = xmlStrcat(str, BAD_CAST "not ");
1908 } else {
1909 is_not = 0;
1910 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001911 /*
1912 * Get the local name.
1913 */
1914 localName = NULL;
1915
1916 end = cur;
1917 if (*end == '*') {
1918 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001919 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001920 } else {
1921 while ((*end != 0) && (*end != '|'))
1922 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001923 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001924 }
1925 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001926 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001927 /*
1928 * Skip "*|*" if they come with negated expressions, since
1929 * they represent the same negated wildcard.
1930 */
1931 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1932 /*
1933 * Get the namespace name.
1934 */
1935 cur = end;
1936 if (*end == '*') {
1937 nsName = xmlStrdup(BAD_CAST "{*}");
1938 } else {
1939 while (*end != 0)
1940 end++;
1941
1942 if (i >= nbval)
1943 nsName = xmlStrdup(BAD_CAST "{##other:");
1944 else
1945 nsName = xmlStrdup(BAD_CAST "{");
1946
1947 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1948 nsName = xmlStrcat(nsName, BAD_CAST "}");
1949 }
1950 str = xmlStrcat(str, BAD_CAST nsName);
1951 FREE_AND_NULL(nsName)
1952 } else {
1953 FREE_AND_NULL(localName);
1954 continue;
1955 }
1956 }
1957 str = xmlStrcat(str, BAD_CAST localName);
1958 FREE_AND_NULL(localName);
1959
1960 if (i < nbval + nbneg -1)
1961 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001962 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001963 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001964 msg = xmlStrcat(msg, BAD_CAST str);
1965 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001966 } else
1967 msg = xmlStrcat(msg, BAD_CAST "\n");
1968 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001969 xmlFree(msg);
1970}
1971
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001972static void
1973xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1974 xmlParserErrors error,
1975 xmlNodePtr node,
1976 const xmlChar *value,
1977 unsigned long length,
1978 xmlSchemaTypePtr type,
1979 xmlSchemaFacetPtr facet,
1980 const char *message,
1981 const xmlChar *str1,
1982 const xmlChar *str2)
1983{
1984 xmlChar *str = NULL, *msg = NULL;
1985 xmlSchemaTypeType facetType;
1986 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1987
1988 xmlSchemaFormatNodeForError(&msg, actxt, node);
1989 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1990 facetType = XML_SCHEMA_FACET_ENUMERATION;
1991 /*
1992 * If enumerations are validated, one must not expect the
1993 * facet to be given.
1994 */
1995 } else
1996 facetType = facet->type;
1997 msg = xmlStrcat(msg, BAD_CAST "[");
1998 msg = xmlStrcat(msg, BAD_CAST "facet '");
1999 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2000 msg = xmlStrcat(msg, BAD_CAST "'] ");
2001 if (message == NULL) {
2002 /*
2003 * Use a default message.
2004 */
2005 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2006 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2007 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2008
2009 char len[25], actLen[25];
2010
2011 /* FIXME, TODO: What is the max expected string length of the
2012 * this value?
2013 */
2014 if (nodeType == XML_ATTRIBUTE_NODE)
2015 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2016 else
2017 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2018
2019 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2020 snprintf(actLen, 24, "%lu", length);
2021
2022 if (facetType == XML_SCHEMA_FACET_LENGTH)
2023 msg = xmlStrcat(msg,
2024 BAD_CAST "this differs from the allowed length of '%s'.\n");
2025 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2026 msg = xmlStrcat(msg,
2027 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2028 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2029 msg = xmlStrcat(msg,
2030 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2031
2032 if (nodeType == XML_ATTRIBUTE_NODE)
2033 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2034 value, (const xmlChar *) actLen, (const xmlChar *) len);
2035 else
2036 xmlSchemaErr(actxt, error, node, (const char *) msg,
2037 (const xmlChar *) actLen, (const xmlChar *) len);
2038
2039 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2040 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2041 "of the set {%s}.\n");
2042 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2043 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2044 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2045 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2046 "by the pattern '%s'.\n");
2047 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2048 facet->value);
2049 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2050 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2051 "minimum value allowed ('%s').\n");
2052 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2053 facet->value);
2054 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2055 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2056 "maximum value allowed ('%s').\n");
2057 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2058 facet->value);
2059 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2060 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2061 "'%s'.\n");
2062 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2063 facet->value);
2064 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2065 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2066 "'%s'.\n");
2067 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2068 facet->value);
2069 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2070 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2071 "digits than are allowed ('%s').\n");
2072 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2073 facet->value);
2074 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2075 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2076 "digits than are allowed ('%s').\n");
2077 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2078 facet->value);
2079 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2080 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2081 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2082 } else {
2083 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2084 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2085 }
2086 } else {
2087 msg = xmlStrcat(msg, (const xmlChar *) message);
2088 msg = xmlStrcat(msg, BAD_CAST ".\n");
2089 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2090 }
2091 FREE_AND_NULL(str)
2092 xmlFree(msg);
2093}
2094
2095#define VERROR(err, type, msg) \
2096 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2097
2098#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2099
2100#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2101
2102#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2103
2104
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002105/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002106 * xmlSchemaPMissingAttrErr:
2107 * @ctxt: the schema validation context
2108 * @ownerDes: the designation of the owner
2109 * @ownerName: the name of the owner
2110 * @ownerItem: the owner as a schema object
2111 * @ownerElem: the owner as an element node
2112 * @node: the parent element node of the missing attribute node
2113 * @type: the corresponding type of the attribute node
2114 *
2115 * Reports an illegal attribute.
2116 */
2117static void
2118xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002119 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002120 xmlSchemaTypePtr ownerItem,
2121 xmlNodePtr ownerElem,
2122 const char *name,
2123 const char *message)
2124{
2125 xmlChar *des = NULL;
2126
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002127 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2128
Daniel Veillardc0826a72004-08-10 14:17:33 +00002129 if (message != NULL)
2130 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002131 else
2132 xmlSchemaPErr(ctxt, ownerElem, error,
2133 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002134 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002135 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002136}
2137
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002138
Daniel Veillardc0826a72004-08-10 14:17:33 +00002139/**
2140 * xmlSchemaPResCompAttrErr:
2141 * @ctxt: the schema validation context
2142 * @error: the error code
2143 * @ownerDes: the designation of the owner
2144 * @ownerItem: the owner as a schema object
2145 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002146 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002147 * @refName: the referenced local name
2148 * @refURI: the referenced namespace URI
2149 * @message: optional message
2150 *
2151 * Used to report QName attribute values that failed to resolve
2152 * to schema components.
2153 */
2154static void
2155xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002156 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002157 xmlSchemaTypePtr ownerItem,
2158 xmlNodePtr ownerElem,
2159 const char *name,
2160 const xmlChar *refName,
2161 const xmlChar *refURI,
2162 xmlSchemaTypeType refType,
2163 const char *refTypeStr)
2164{
2165 xmlChar *des = NULL, *strA = NULL;
2166
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002167 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002168 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002169 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2170 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002171 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002172 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2173 "%s.\n", BAD_CAST des, BAD_CAST name,
2174 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002175 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002176 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002177 FREE_AND_NULL(strA)
2178}
2179
William M. Brack2f2a6632004-08-20 23:09:47 +00002180/**
2181 * xmlSchemaPCustomAttrErr:
2182 * @ctxt: the schema parser context
2183 * @error: the error code
2184 * @ownerDes: the designation of the owner
2185 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002186 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002187 *
2188 * Reports an illegal attribute during the parse.
2189 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002190static void
2191xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002192 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002193 xmlChar **ownerDes,
2194 xmlSchemaTypePtr ownerItem,
2195 xmlAttrPtr attr,
2196 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197{
2198 xmlChar *des = NULL;
2199
2200 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002201 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002202 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002203 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002204 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002205 } else
2206 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002207 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002208 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002209 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2210 if (ownerDes == NULL)
2211 FREE_AND_NULL(des);
2212}
2213
2214/**
2215 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002216 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002217 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002218 * @ownerDes: the designation of the attribute's owner
2219 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002220 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002221 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002222 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002223 */
2224static void
2225xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002226 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002227 xmlChar **ownerDes,
2228 xmlSchemaTypePtr ownerItem,
2229 xmlAttrPtr attr)
2230{
2231 xmlChar *des = NULL, *strA = NULL;
2232
2233 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002234 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002235 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002236 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002237 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002238 } else
2239 des = *ownerDes;
2240 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2241 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2242 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002243 if (ownerDes == NULL)
2244 FREE_AND_NULL(des);
2245 FREE_AND_NULL(strA);
2246}
2247
William M. Brack2f2a6632004-08-20 23:09:47 +00002248/**
2249 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002250 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002251 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002252 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002253 * @itemElem: the node of the schema item
2254 *
2255 * Creates a designation for an item.
2256 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002257static void
2258xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002259 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002260 xmlSchemaTypePtr item,
2261 xmlNodePtr itemElem)
2262{
2263 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002264 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002265 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002266 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002267 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002268 } else
2269 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002270}
2271
William M. Brack2f2a6632004-08-20 23:09:47 +00002272/**
2273 * xmlSchemaPCustomErr:
2274 * @ctxt: the schema parser context
2275 * @error: the error code
2276 * @itemDes: the designation of the schema item
2277 * @item: the schema item
2278 * @itemElem: the node of the schema item
2279 * @message: the error message
2280 * @str1: an optional param for the error message
2281 * @str2: an optional param for the error message
2282 * @str3: an optional param for the error message
2283 *
2284 * Reports an error during parsing.
2285 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002286static void
2287xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002288 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002289 xmlChar **itemDes,
2290 xmlSchemaTypePtr item,
2291 xmlNodePtr itemElem,
2292 const char *message,
2293 const xmlChar *str1,
2294 const xmlChar *str2,
2295 const xmlChar *str3)
2296{
2297 xmlChar *des = NULL, *msg = NULL;
2298
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002299 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002300 msg = xmlStrdup(BAD_CAST "%s: ");
2301 msg = xmlStrcat(msg, (const xmlChar *) message);
2302 msg = xmlStrcat(msg, BAD_CAST ".\n");
2303 if ((itemElem == NULL) && (item != NULL))
2304 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002305 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002306 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2307 if (itemDes == NULL)
2308 FREE_AND_NULL(des);
2309 FREE_AND_NULL(msg);
2310}
2311
William M. Brack2f2a6632004-08-20 23:09:47 +00002312/**
2313 * xmlSchemaPCustomErr:
2314 * @ctxt: the schema parser context
2315 * @error: the error code
2316 * @itemDes: the designation of the schema item
2317 * @item: the schema item
2318 * @itemElem: the node of the schema item
2319 * @message: the error message
2320 * @str1: the optional param for the error message
2321 *
2322 * Reports an error during parsing.
2323 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002324static void
2325xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002326 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002327 xmlChar **itemDes,
2328 xmlSchemaTypePtr item,
2329 xmlNodePtr itemElem,
2330 const char *message,
2331 const xmlChar *str1)
2332{
2333 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2334 str1, NULL, NULL);
2335}
2336
William M. Brack2f2a6632004-08-20 23:09:47 +00002337/**
2338 * xmlSchemaPAttrUseErr:
2339 * @ctxt: the schema parser context
2340 * @error: the error code
2341 * @itemDes: the designation of the schema type
2342 * @item: the schema type
2343 * @itemElem: the node of the schema type
2344 * @attr: the invalid schema attribute
2345 * @message: the error message
2346 * @str1: the optional param for the error message
2347 *
2348 * Reports an attribute use error during parsing.
2349 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002350static void
2351xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002352 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002353 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002354 const xmlSchemaAttributePtr attr,
2355 const char *message,
2356 const xmlChar *str1)
2357{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002358 xmlChar *str = NULL, *msg = NULL;
2359 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2360 msg = xmlStrcat(msg, BAD_CAST ", ");
2361 msg = xmlStrcat(msg,
2362 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2363 (xmlSchemaTypePtr) attr, NULL));
2364 FREE_AND_NULL(str);
2365 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002366 msg = xmlStrcat(msg, (const xmlChar *) message);
2367 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002368 xmlSchemaPErr(ctxt, attr->node, error,
2369 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002370 xmlFree(msg);
2371}
2372
William M. Brack2f2a6632004-08-20 23:09:47 +00002373/**
2374 * xmlSchemaPIllegalFacetAtomicErr:
2375 * @ctxt: the schema parser context
2376 * @error: the error code
2377 * @itemDes: the designation of the type
2378 * @item: the schema type
2379 * @baseItem: the base type of type
2380 * @facet: the illegal facet
2381 *
2382 * Reports an illegal facet for atomic simple types.
2383 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002384static void
2385xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002386 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002387 xmlChar **itemDes,
2388 xmlSchemaTypePtr item,
2389 xmlSchemaTypePtr baseItem,
2390 xmlSchemaFacetPtr facet)
2391{
2392 xmlChar *des = NULL, *strT = NULL;
2393
2394 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2395 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2396 "%s: The facet '%s' is not allowed on types derived from the "
2397 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002398 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002399 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002400 NULL, NULL);
2401 if (itemDes == NULL)
2402 FREE_AND_NULL(des);
2403 FREE_AND_NULL(strT);
2404}
2405
William M. Brack2f2a6632004-08-20 23:09:47 +00002406/**
2407 * xmlSchemaPIllegalFacetListUnionErr:
2408 * @ctxt: the schema parser context
2409 * @error: the error code
2410 * @itemDes: the designation of the schema item involved
2411 * @item: the schema item involved
2412 * @facet: the illegal facet
2413 *
2414 * Reports an illegal facet for <list> and <union>.
2415 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002416static void
2417xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002418 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002419 xmlChar **itemDes,
2420 xmlSchemaTypePtr item,
2421 xmlSchemaFacetPtr facet)
2422{
2423 xmlChar *des = NULL, *strT = NULL;
2424
2425 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002426 xmlSchemaPErr(ctxt, item->node, error,
2427 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002428 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002429 if (itemDes == NULL)
2430 FREE_AND_NULL(des);
2431 FREE_AND_NULL(strT);
2432}
2433
2434/**
2435 * xmlSchemaPMutualExclAttrErr:
2436 * @ctxt: the schema validation context
2437 * @error: the error code
2438 * @elemDes: the designation of the parent element node
2439 * @attr: the bad attribute node
2440 * @type: the corresponding type of the attribute node
2441 *
2442 * Reports an illegal attribute.
2443 */
2444static void
2445xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2446 xmlParserErrors error,
2447 xmlChar **ownerDes,
2448 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002449 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002450 const char *name1,
2451 const char *name2)
2452{
2453 xmlChar *des = NULL;
2454
2455 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002456 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002457 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002458 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002459 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002460 } else
2461 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002462 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002463 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002464 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2465 if (ownerDes == NULL)
2466 FREE_AND_NULL(des)
2467}
2468
2469/**
2470 * xmlSchemaPSimpleTypeErr:
2471 * @ctxt: the schema validation context
2472 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002473 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002474 * @ownerDes: the designation of the owner
2475 * @ownerItem: the schema object if existent
2476 * @node: the validated node
2477 * @value: the validated value
2478 *
2479 * Reports a simple type validation error.
2480 * TODO: Should this report the value of an element as well?
2481 */
2482static void
2483xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2484 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002485 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002486 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002487 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002488 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002489 const xmlChar *value,
2490 const char *message,
2491 const xmlChar *str1,
2492 const xmlChar *str2)
2493{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002494 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002495
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002496 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002497 if (message == NULL) {
2498 /*
2499 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002500 */
2501 if (type != NULL) {
2502 if (node->type == XML_ATTRIBUTE_NODE)
2503 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2504 else
2505 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2506 "valid value of ");
2507 if (! xmlSchemaIsGlobalItem(type))
2508 msg = xmlStrcat(msg, BAD_CAST "the local ");
2509 else
2510 msg = xmlStrcat(msg, BAD_CAST "the ");
2511
2512 if (VARIETY_ATOMIC(type))
2513 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2514 else if (VARIETY_LIST(type))
2515 msg = xmlStrcat(msg, BAD_CAST "list type");
2516 else if (VARIETY_UNION(type))
2517 msg = xmlStrcat(msg, BAD_CAST "union type");
2518
2519 if (xmlSchemaIsGlobalItem(type)) {
2520 xmlChar *str = NULL;
2521 msg = xmlStrcat(msg, BAD_CAST " '");
2522 if (type->builtInType != 0) {
2523 msg = xmlStrcat(msg, BAD_CAST "xs:");
2524 msg = xmlStrcat(msg, type->name);
2525 } else
2526 msg = xmlStrcat(msg,
2527 xmlSchemaFormatQName(&str,
2528 type->targetNamespace, type->name));
2529 msg = xmlStrcat(msg, BAD_CAST "'.");
2530 FREE_AND_NULL(str);
2531 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002532 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002533 if (node->type == XML_ATTRIBUTE_NODE)
2534 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2535 else
2536 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2537 "valid.");
2538 }
2539 if (expected) {
2540 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2541 msg = xmlStrcat(msg, BAD_CAST expected);
2542 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2543 } else
2544 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002545 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002546 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2547 else
2548 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2549 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002550 msg = xmlStrcat(msg, BAD_CAST message);
2551 msg = xmlStrcat(msg, BAD_CAST "\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002552 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002553 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002554 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002555 /* Cleanup. */
2556 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002557}
2558
William M. Brack2f2a6632004-08-20 23:09:47 +00002559/**
2560 * xmlSchemaPContentErr:
2561 * @ctxt: the schema parser context
2562 * @error: the error code
2563 * @onwerDes: the designation of the holder of the content
2564 * @ownerItem: the owner item of the holder of the content
2565 * @ownerElem: the node of the holder of the content
2566 * @child: the invalid child node
2567 * @message: the optional error message
2568 * @content: the optional string describing the correct content
2569 *
2570 * Reports an error concerning the content of a schema element.
2571 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002572static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002573xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002574 xmlParserErrors error,
2575 xmlChar **ownerDes,
2576 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002577 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002578 xmlNodePtr child,
2579 const char *message,
2580 const char *content)
2581{
2582 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002583
Daniel Veillardc0826a72004-08-10 14:17:33 +00002584 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002585 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002586 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002587 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002588 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002589 } else
2590 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002591 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002592 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2593 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002594 BAD_CAST des, BAD_CAST message);
2595 else {
2596 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002597 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2598 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002599 BAD_CAST des, BAD_CAST content);
2600 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002601 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2602 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002603 BAD_CAST des, NULL);
2604 }
2605 }
2606 if (ownerDes == NULL)
2607 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002608}
2609
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002610/************************************************************************
2611 * *
2612 * Streamable error functions *
2613 * *
2614 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002615
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002616
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002617
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002618
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002619/************************************************************************
2620 * *
2621 * Validation helper functions *
2622 * *
2623 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002624
Daniel Veillardc0826a72004-08-10 14:17:33 +00002625
Daniel Veillard4255d502002-04-16 15:50:10 +00002626/************************************************************************
2627 * *
2628 * Allocation functions *
2629 * *
2630 ************************************************************************/
2631
2632/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002633 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002634 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002635 *
2636 * Allocate a new Schema structure.
2637 *
2638 * Returns the newly allocated structure or NULL in case or error
2639 */
2640static xmlSchemaPtr
2641xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2642{
2643 xmlSchemaPtr ret;
2644
2645 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2646 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002647 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002648 return (NULL);
2649 }
2650 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002651 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002652 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002653
2654 return (ret);
2655}
2656
2657/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002658 * xmlSchemaNewSchema:
2659 * @ctxt: a schema validation context
2660 *
2661 * Allocate a new Schema structure.
2662 *
2663 * Returns the newly allocated structure or NULL in case or error
2664 */
2665static xmlSchemaAssemblePtr
2666xmlSchemaNewAssemble(void)
2667{
2668 xmlSchemaAssemblePtr ret;
2669
2670 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2671 if (ret == NULL) {
2672 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2673 return (NULL);
2674 }
2675 memset(ret, 0, sizeof(xmlSchemaAssemble));
2676 ret->items = NULL;
2677 return (ret);
2678}
2679
2680/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002681 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002682 *
2683 * Allocate a new Facet structure.
2684 *
2685 * Returns the newly allocated structure or NULL in case or error
2686 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002687xmlSchemaFacetPtr
2688xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002689{
2690 xmlSchemaFacetPtr ret;
2691
2692 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2693 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002694 return (NULL);
2695 }
2696 memset(ret, 0, sizeof(xmlSchemaFacet));
2697
2698 return (ret);
2699}
2700
2701/**
2702 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002703 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002704 * @node: a node
2705 *
2706 * Allocate a new annotation structure.
2707 *
2708 * Returns the newly allocated structure or NULL in case or error
2709 */
2710static xmlSchemaAnnotPtr
2711xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2712{
2713 xmlSchemaAnnotPtr ret;
2714
2715 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2716 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002717 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002718 return (NULL);
2719 }
2720 memset(ret, 0, sizeof(xmlSchemaAnnot));
2721 ret->content = node;
2722 return (ret);
2723}
2724
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002725static xmlSchemaItemListPtr
2726xmlSchemaNewItemList(void)
2727{
2728 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002729
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002730 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2731 if (ret == NULL) {
2732 xmlSchemaPErrMemory(NULL,
2733 "allocating an item list structure", NULL);
2734 return (NULL);
2735 }
2736 memset(ret, 0, sizeof(xmlSchemaItemList));
2737 return (ret);
2738}
2739
2740/**
2741 * xmlSchemaAddElementSubstitutionMember:
2742 * @pctxt: a schema parser context
2743 * @head: the head of the substitution group
2744 * @member: the new member of the substitution group
2745 *
2746 * Allocate a new annotation structure.
2747 *
2748 * Returns the newly allocated structure or NULL in case or error
2749 */
2750static int
2751xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2752 xmlSchemaElementPtr head,
2753 xmlSchemaElementPtr member)
2754{
2755 xmlSchemaSubstGroupPtr substGroup;
2756
2757 if (pctxt == NULL)
2758 return (-1);
2759
2760 if (pctxt->substGroups == NULL) {
2761 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2762 if (pctxt->substGroups == NULL)
2763 return (-1);
2764 }
2765 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2766 head->targetNamespace);
2767 if (substGroup == NULL) {
2768 int res;
2769
2770 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2771 if (substGroup == NULL) {
2772 xmlSchemaPErrMemory(NULL,
2773 "xmlSchemaAddElementSubstitution, allocating a substitution "
2774 "group container",
2775 NULL);
2776 return (-1);
2777 }
2778 substGroup->members = xmlSchemaNewItemList();
2779 if (substGroup->members == NULL) {
2780 xmlFree(substGroup);
2781 return (-1);
2782 }
2783 substGroup->head = head;
2784
2785 res = xmlHashAddEntry2(pctxt->substGroups,
2786 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002787 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002788 xmlFree(substGroup->members);
2789 xmlFree(substGroup);
2790 xmlSchemaPErr(pctxt, member->node,
2791 XML_SCHEMAP_INTERNAL,
2792 "Internal error: xmlSchemaAddElementSubstitution, "
2793 "failed to add a new substitution group container for "
2794 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002795 return (-1);
2796 }
2797 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002798 if (substGroup->members->items == NULL) {
2799 substGroup->members->items = (void **) xmlMalloc(
2800 5 * sizeof(xmlSchemaElementPtr));
2801 if (substGroup->members->items == NULL) {
2802 xmlSchemaPErrMemory(NULL,
2803 "allocating list of substitution group members", NULL);
2804 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002805 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002806 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002807 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002808 substGroup->members->nbItems) {
2809 substGroup->members->sizeItems *= 2;
2810 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002811 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002812 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2813 if (substGroup->members->items == NULL) {
2814 xmlSchemaPErrMemory(NULL,
2815 "re-allocating list of substitution group members", NULL);
2816 substGroup->members->sizeItems = 0;
2817 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002818 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002819 }
2820 ((xmlSchemaElementPtr *) substGroup->members->items)
2821 [substGroup->members->nbItems++] = (void *) member;
2822 return (0);
2823}
2824
2825/**
2826 * xmlSchemaGetElementSubstitutionGroup:
2827 * @pctxt: a schema parser context
2828 * @head: the head of the substitution group
2829 * @member: the new member of the substitution group
2830 *
2831 * Allocate a new annotation structure.
2832 *
2833 * Returns the newly allocated structure or NULL in case or error
2834 */
2835static xmlSchemaSubstGroupPtr
2836xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2837 xmlSchemaElementPtr head)
2838{
2839 if (pctxt == NULL)
2840 return (NULL);
2841
2842 if (pctxt->substGroups == NULL)
2843 return (NULL);
2844
2845 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2846 head->name, head->targetNamespace));
2847}
2848
2849/**
2850 * xmlSchemaFreeItemList:
2851 * @annot: a schema type structure
2852 *
2853 * Deallocate a annotation structure
2854 */
2855static void
2856xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2857{
2858 if (list == NULL)
2859 return;
2860 if (list->items != NULL)
2861 xmlFree(list->items);
2862 xmlFree(list);
2863}
2864
Daniel Veillard4255d502002-04-16 15:50:10 +00002865/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002866 * xmlSchemaFreeAnnot:
2867 * @annot: a schema type structure
2868 *
2869 * Deallocate a annotation structure
2870 */
2871static void
2872xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2873{
2874 if (annot == NULL)
2875 return;
2876 xmlFree(annot);
2877}
2878
2879/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002880 * xmlSchemaFreeImport:
2881 * @import: a schema import structure
2882 *
2883 * Deallocate an import structure
2884 */
2885static void
2886xmlSchemaFreeImport(xmlSchemaImportPtr import)
2887{
2888 if (import == NULL)
2889 return;
2890
2891 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002892 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002893 xmlFree(import);
2894}
2895
2896/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002897 * xmlSchemaFreeInclude:
2898 * @include: a schema include structure
2899 *
2900 * Deallocate an include structure
2901 */
2902static void
2903xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2904{
2905 if (include == NULL)
2906 return;
2907
2908 xmlFreeDoc(include->doc);
2909 xmlFree(include);
2910}
2911
2912/**
2913 * xmlSchemaFreeIncludeList:
2914 * @includes: a schema include list
2915 *
2916 * Deallocate an include structure
2917 */
2918static void
2919xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2920{
2921 xmlSchemaIncludePtr next;
2922
2923 while (includes != NULL) {
2924 next = includes->next;
2925 xmlSchemaFreeInclude(includes);
2926 includes = next;
2927 }
2928}
2929
2930/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002931 * xmlSchemaFreeNotation:
2932 * @schema: a schema notation structure
2933 *
2934 * Deallocate a Schema Notation structure.
2935 */
2936static void
2937xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2938{
2939 if (nota == NULL)
2940 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002941 xmlFree(nota);
2942}
2943
2944/**
2945 * xmlSchemaFreeAttribute:
2946 * @schema: a schema attribute structure
2947 *
2948 * Deallocate a Schema Attribute structure.
2949 */
2950static void
2951xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2952{
2953 if (attr == NULL)
2954 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002955 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002956 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002957 if (attr->defVal != NULL)
2958 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002959 xmlFree(attr);
2960}
2961
2962/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002963 * xmlSchemaFreeWildcardNsSet:
2964 * set: a schema wildcard namespace
2965 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002966 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002967 */
2968static void
2969xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2970{
2971 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002972
Daniel Veillard3646d642004-06-02 19:19:14 +00002973 while (set != NULL) {
2974 next = set->next;
2975 xmlFree(set);
2976 set = next;
2977 }
2978}
2979
2980/**
2981 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002982 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002983 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002984 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002985 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002986void
Daniel Veillard3646d642004-06-02 19:19:14 +00002987xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2988{
2989 if (wildcard == NULL)
2990 return;
2991 if (wildcard->annot != NULL)
2992 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002993 if (wildcard->nsSet != NULL)
2994 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2995 if (wildcard->negNsSet != NULL)
2996 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002997 xmlFree(wildcard);
2998}
2999
3000/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003001 * xmlSchemaFreeAttributeGroup:
3002 * @schema: a schema attribute group structure
3003 *
3004 * Deallocate a Schema Attribute Group structure.
3005 */
3006static void
3007xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3008{
3009 if (attr == NULL)
3010 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003011 if (attr->annot != NULL)
3012 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003013 xmlFree(attr);
3014}
3015
3016/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003017 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003018 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003019 *
3020 * Deallocate a list of schema attribute uses.
3021 */
3022static void
3023xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3024{
3025 xmlSchemaAttributeLinkPtr next;
3026
3027 while (attrUse != NULL) {
3028 next = attrUse->next;
3029 xmlFree(attrUse);
3030 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003031 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003032}
3033
3034/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003035 * xmlSchemaFreeQNameRef:
3036 * @item: a QName reference structure
3037 *
3038 * Deallocatea a QName reference structure.
3039 */
3040static void
3041xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3042{
3043 xmlFree(item);
3044}
3045
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003046/**
3047 * xmlSchemaFreeQNameRef:
3048 * @item: a QName reference structure
3049 *
3050 * Deallocatea a QName reference structure.
3051 */
3052static void
3053xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3054{
3055 if (item == NULL)
3056 return;
3057 if (item->members != NULL)
3058 xmlSchemaFreeItemList(item->members);
3059 xmlFree(item);
3060}
3061
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003062static int
3063xmlSchemaAddVolatile(xmlSchemaPtr schema,
3064 xmlSchemaBasicItemPtr item)
3065{
3066 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003067
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003068 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003069 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003070 if (schema->volatiles == NULL) {
3071 xmlSchemaPErrMemory(NULL,
3072 "allocating list of volatiles", NULL);
3073 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003074 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003075 }
3076 list = (xmlSchemaItemListPtr) schema->volatiles;
3077 if (list->items == NULL) {
3078 list->items = (void **) xmlMalloc(
3079 20 * sizeof(xmlSchemaBasicItemPtr));
3080 if (list->items == NULL) {
3081 xmlSchemaPErrMemory(NULL,
3082 "allocating new volatile item buffer", NULL);
3083 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003084 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003085 list->sizeItems = 20;
3086 } else if (list->sizeItems <= list->nbItems) {
3087 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003088 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003089 list->sizeItems * sizeof(xmlSchemaTypePtr));
3090 if (list->items == NULL) {
3091 xmlSchemaPErrMemory(NULL,
3092 "growing volatile item buffer", NULL);
3093 list->sizeItems = 0;
3094 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003095 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003096 }
3097 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3098 return (0);
3099}
3100
3101/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003102 * xmlSchemaFreeTypeLinkList:
3103 * @alink: a type link
3104 *
3105 * Deallocate a list of types.
3106 */
3107static void
3108xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3109{
3110 xmlSchemaTypeLinkPtr next;
3111
3112 while (link != NULL) {
3113 next = link->next;
3114 xmlFree(link);
3115 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003116 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003117}
3118
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003119static void
3120xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3121{
3122 xmlSchemaIDCStateObjPtr next;
3123 while (sto != NULL) {
3124 next = sto->next;
3125 if (sto->history != NULL)
3126 xmlFree(sto->history);
3127 if (sto->xpathCtxt != NULL)
3128 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3129 xmlFree(sto);
3130 sto = next;
3131 }
3132}
3133
3134/**
3135 * xmlSchemaFreeIDC:
3136 * @idc: a identity-constraint definition
3137 *
3138 * Deallocates an identity-constraint definition.
3139 */
3140static void
3141xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3142{
3143 xmlSchemaIDCSelectPtr cur, prev;
3144
3145 if (idcDef == NULL)
3146 return;
3147 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003148 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003149 /* Selector */
3150 if (idcDef->selector != NULL) {
3151 if (idcDef->selector->xpathComp != NULL)
3152 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3153 xmlFree(idcDef->selector);
3154 }
3155 /* Fields */
3156 if (idcDef->fields != NULL) {
3157 cur = idcDef->fields;
3158 do {
3159 prev = cur;
3160 cur = cur->next;
3161 if (prev->xpathComp != NULL)
3162 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003163 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003164 } while (cur != NULL);
3165 }
3166 xmlFree(idcDef);
3167}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003168
Daniel Veillard01fa6152004-06-29 17:04:39 +00003169/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003170 * xmlSchemaFreeElement:
3171 * @schema: a schema element structure
3172 *
3173 * Deallocate a Schema Element structure.
3174 */
3175static void
3176xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3177{
3178 if (elem == NULL)
3179 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003180 if (elem->annot != NULL)
3181 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003182 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003183 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003184 if (elem->defVal != NULL)
3185 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003186 xmlFree(elem);
3187}
3188
3189/**
3190 * xmlSchemaFreeFacet:
3191 * @facet: a schema facet structure
3192 *
3193 * Deallocate a Schema Facet structure.
3194 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003195void
Daniel Veillard4255d502002-04-16 15:50:10 +00003196xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3197{
3198 if (facet == NULL)
3199 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003200 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003201 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003202 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003203 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003204 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003205 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003206 xmlFree(facet);
3207}
3208
3209/**
3210 * xmlSchemaFreeType:
3211 * @type: a schema type structure
3212 *
3213 * Deallocate a Schema Type structure.
3214 */
3215void
3216xmlSchemaFreeType(xmlSchemaTypePtr type)
3217{
3218 if (type == NULL)
3219 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003220 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003221 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003222 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003223 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003224
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003225 facet = type->facets;
3226 while (facet != NULL) {
3227 next = facet->next;
3228 xmlSchemaFreeFacet(facet);
3229 facet = next;
3230 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003231 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003232 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3233 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003234 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003235 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003236 if (type->memberTypes != NULL)
3237 xmlSchemaFreeTypeLinkList(type->memberTypes);
3238 if (type->facetSet != NULL) {
3239 xmlSchemaFacetLinkPtr next, link;
3240
3241 link = type->facetSet;
3242 do {
3243 next = link->next;
3244 xmlFree(link);
3245 link = next;
3246 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003247 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003248 if (type->contModel != NULL)
3249 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003250 xmlFree(type);
3251}
3252
3253/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003254 * xmlSchemaFreeModelGroupDef:
3255 * @item: a schema model group definition
3256 *
3257 * Deallocates a schema model group definition.
3258 */
3259static void
3260xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3261{
3262 if (item->annot != NULL)
3263 xmlSchemaFreeAnnot(item->annot);
3264 xmlFree(item);
3265}
3266
3267/**
3268 * xmlSchemaFreeModelGroup:
3269 * @item: a schema model group
3270 *
3271 * Deallocates a schema model group structure.
3272 */
3273static void
3274xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3275{
3276 if (item->annot != NULL)
3277 xmlSchemaFreeAnnot(item->annot);
3278 xmlFree(item);
3279}
3280
3281/**
3282 * xmlSchemaFreeParticle:
3283 * @type: a schema type structure
3284 *
3285 * Deallocate a Schema Type structure.
3286 */
3287static void
3288xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3289{
3290 if (item->annot != NULL)
3291 xmlSchemaFreeAnnot(item->annot);
3292 xmlFree(item);
3293}
3294
3295/**
3296 * xmlSchemaFreeMiscComponents:
3297 * @item: a schema component
3298 *
3299 * Deallocates misc. schema component structures.
3300 */
3301static void
3302xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3303{
3304 if (item == NULL)
3305 return;
3306 switch (item->type) {
3307 case XML_SCHEMA_TYPE_PARTICLE:
3308 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3309 return;
3310 case XML_SCHEMA_TYPE_SEQUENCE:
3311 case XML_SCHEMA_TYPE_CHOICE:
3312 case XML_SCHEMA_TYPE_ALL:
3313 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3314 return;
3315 case XML_SCHEMA_TYPE_ANY:
3316 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3317 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3318 break;
3319 default:
3320 /* TODO: This should never be hit. */
3321 TODO
3322 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003323 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003324}
3325
3326static void
3327xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3328{
3329 if (schema->volatiles == NULL)
3330 return;
3331 {
3332 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3333 xmlSchemaTreeItemPtr item;
3334 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003336 for (i = 0; i < list->nbItems; i++) {
3337 if (list->items[i] != NULL) {
3338 item = (xmlSchemaTreeItemPtr) list->items[i];
3339 switch (item->type) {
3340 case XML_SCHEMA_EXTRA_QNAMEREF:
3341 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3342 break;
3343 default:
3344 xmlSchemaFreeMiscComponents(item);
3345 }
3346 }
3347 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003348 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003349 }
3350}
3351/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003352 * xmlSchemaFreeTypeList:
3353 * @type: a schema type structure
3354 *
3355 * Deallocate a Schema Type structure.
3356 */
3357static void
3358xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3359{
3360 xmlSchemaTypePtr next;
3361
3362 while (type != NULL) {
3363 next = type->redef;
3364 xmlSchemaFreeType(type);
3365 type = next;
3366 }
3367}
3368
3369/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003370 * xmlSchemaFree:
3371 * @schema: a schema structure
3372 *
3373 * Deallocate a Schema structure.
3374 */
3375void
3376xmlSchemaFree(xmlSchemaPtr schema)
3377{
3378 if (schema == NULL)
3379 return;
3380
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003381 if (schema->volatiles != NULL)
3382 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003383 if (schema->notaDecl != NULL)
3384 xmlHashFree(schema->notaDecl,
3385 (xmlHashDeallocator) xmlSchemaFreeNotation);
3386 if (schema->attrDecl != NULL)
3387 xmlHashFree(schema->attrDecl,
3388 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3389 if (schema->attrgrpDecl != NULL)
3390 xmlHashFree(schema->attrgrpDecl,
3391 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3392 if (schema->elemDecl != NULL)
3393 xmlHashFree(schema->elemDecl,
3394 (xmlHashDeallocator) xmlSchemaFreeElement);
3395 if (schema->typeDecl != NULL)
3396 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003397 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003398 if (schema->groupDecl != NULL)
3399 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003400 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003401 if (schema->idcDef != NULL)
3402 xmlHashFree(schema->idcDef,
3403 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003404 if (schema->schemasImports != NULL)
3405 xmlHashFree(schema->schemasImports,
3406 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003407 if (schema->includes != NULL) {
3408 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3409 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003410 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003411 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003412 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003413 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003414 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003415 xmlFree(schema);
3416}
3417
3418/************************************************************************
3419 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003420 * Debug functions *
3421 * *
3422 ************************************************************************/
3423
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003424#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003425
Daniel Veillard4255d502002-04-16 15:50:10 +00003426/**
3427 * xmlSchemaElementDump:
3428 * @elem: an element
3429 * @output: the file output
3430 *
3431 * Dump the element
3432 */
3433static void
3434xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003435 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003436 const xmlChar * namespace ATTRIBUTE_UNUSED,
3437 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003438{
3439 if (elem == NULL)
3440 return;
3441
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003442 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3443 fprintf(output, "Particle: %s", name);
3444 fprintf(output, ", term element: %s", elem->ref);
3445 if (elem->refNs != NULL)
3446 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003447 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003448 fprintf(output, "Element");
3449 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3450 fprintf(output, " (global)");
3451 fprintf(output, ": %s ", elem->name);
3452 if (namespace != NULL)
3453 fprintf(output, "ns %s", namespace);
3454 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003455 fprintf(output, "\n");
3456 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003457 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003458 if (elem->maxOccurs >= UNBOUNDED)
3459 fprintf(output, "max: unbounded\n");
3460 else if (elem->maxOccurs != 1)
3461 fprintf(output, "max: %d\n", elem->maxOccurs);
3462 else
3463 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003464 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003465 /*
3466 * Misc other properties.
3467 */
3468 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3469 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3470 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3471 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3472 (elem->id != NULL)) {
3473 fprintf(output, " props: ");
3474 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3475 fprintf(output, "[fixed] ");
3476 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3477 fprintf(output, "[default] ");
3478 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3479 fprintf(output, "[abstract] ");
3480 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3481 fprintf(output, "[nillable] ");
3482 if (elem->id != NULL)
3483 fprintf(output, "[id: '%s'] ", elem->id);
3484 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003485 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003486 /*
3487 * Default/fixed value.
3488 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003489 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003490 fprintf(output, " value: '%s'\n", elem->value);
3491 /*
3492 * Type.
3493 */
3494 if (elem->namedType != NULL) {
3495 fprintf(output, " type: %s ", elem->namedType);
3496 if (elem->namedTypeNs != NULL)
3497 fprintf(output, "ns %s\n", elem->namedTypeNs);
3498 else
3499 fprintf(output, "\n");
3500 }
3501 /*
3502 * Substitution group.
3503 */
3504 if (elem->substGroup != NULL) {
3505 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3506 if (elem->substGroupNs != NULL)
3507 fprintf(output, "ns %s\n", elem->substGroupNs);
3508 else
3509 fprintf(output, "\n");
3510 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003511}
3512
3513/**
3514 * xmlSchemaAnnotDump:
3515 * @output: the file output
3516 * @annot: a annotation
3517 *
3518 * Dump the annotation
3519 */
3520static void
3521xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3522{
3523 xmlChar *content;
3524
3525 if (annot == NULL)
3526 return;
3527
3528 content = xmlNodeGetContent(annot->content);
3529 if (content != NULL) {
3530 fprintf(output, " Annot: %s\n", content);
3531 xmlFree(content);
3532 } else
3533 fprintf(output, " Annot: empty\n");
3534}
3535
3536/**
3537 * xmlSchemaTypeDump:
3538 * @output: the file output
3539 * @type: a type structure
3540 *
3541 * Dump a SchemaType structure
3542 */
3543static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003544xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3545{
3546 xmlChar *str = NULL;
3547 xmlSchemaTreeItemPtr term;
3548 char shift[100];
3549 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003550
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003551 if (particle == NULL)
3552 return;
3553 for (i = 0;((i < depth) && (i < 25));i++)
3554 shift[2 * i] = shift[2 * i + 1] = ' ';
3555 shift[2 * i] = shift[2 * i + 1] = 0;
3556 fprintf(output, shift);
3557 if (particle->children == NULL) {
3558 fprintf(output, "MISSING particle term\n");
3559 return;
3560 }
3561 term = particle->children;
3562 switch (term->type) {
3563 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003564 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003565 ((xmlSchemaElementPtr)term)->targetNamespace,
3566 ((xmlSchemaElementPtr)term)->name));
3567 break;
3568 case XML_SCHEMA_TYPE_SEQUENCE:
3569 fprintf(output, "SEQUENCE");
3570 break;
3571 case XML_SCHEMA_TYPE_CHOICE:
3572 fprintf(output, "CHOICE");
3573 break;
3574 case XML_SCHEMA_TYPE_ALL:
3575 fprintf(output, "ALL");
3576 break;
3577 case XML_SCHEMA_TYPE_ANY:
3578 fprintf(output, "ANY");
3579 break;
3580 default:
3581 fprintf(output, "UNKNOWN\n");
3582 return;
3583 }
3584 if (particle->minOccurs != 1)
3585 fprintf(output, " min: %d", particle->minOccurs);
3586 if (particle->maxOccurs >= UNBOUNDED)
3587 fprintf(output, " max: unbounded");
3588 else if (particle->maxOccurs != 1)
3589 fprintf(output, " max: %d", particle->maxOccurs);
3590 fprintf(output, "\n");
3591 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3592 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3593 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3594 (term->children != NULL)) {
3595 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3596 output, depth +1);
3597 }
3598 if (particle->next != NULL)
3599 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3600 output, depth);
3601}
3602/**
3603 * xmlSchemaTypeDump:
3604 * @output: the file output
3605 * @type: a type structure
3606 *
3607 * Dump a SchemaType structure
3608 */
3609static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003610xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3611{
3612 if (type == NULL) {
3613 fprintf(output, "Type: NULL\n");
3614 return;
3615 }
3616 fprintf(output, "Type: ");
3617 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003618 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003619 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003620 fprintf(output, "no name ");
3621 if (type->targetNamespace != NULL)
3622 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 switch (type->type) {
3624 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003625 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003626 break;
3627 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003628 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 break;
3630 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003631 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 break;
3633 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003634 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003635 break;
3636 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003637 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 break;
3639 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003640 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003641 break;
3642 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003643 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003644 break;
3645 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003646 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003647 break;
3648 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003649 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003650 break;
3651 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003652 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003653 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003654 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003655 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003656 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003657 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003658 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003659 break;
3660 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003661 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003662 break;
3663 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003664 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003665 break;
3666 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003667 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003668 break;
3669 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003670 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003671 break;
3672 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003673 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003674 break;
3675 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003676 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003677 break;
3678 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003679 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003680 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003681 }
3682 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003683 if (type->base != NULL) {
3684 fprintf(output, " base type: %s", type->base);
3685 if (type->baseNs != NULL)
3686 fprintf(output, " ns %s\n", type->baseNs);
3687 else
3688 fprintf(output, "\n");
3689 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003690 if (type->annot != NULL)
3691 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003692#ifdef DUMP_CONTENT_MODEL
3693 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3694 (type->subtypes != NULL)) {
3695 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3696 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003697 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003698#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003699}
3700
3701/**
3702 * xmlSchemaDump:
3703 * @output: the file output
3704 * @schema: a schema structure
3705 *
3706 * Dump a Schema structure.
3707 */
3708void
3709xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3710{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003711 if (output == NULL)
3712 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003713 if (schema == NULL) {
3714 fprintf(output, "Schemas: NULL\n");
3715 return;
3716 }
3717 fprintf(output, "Schemas: ");
3718 if (schema->name != NULL)
3719 fprintf(output, "%s, ", schema->name);
3720 else
3721 fprintf(output, "no name, ");
3722 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003723 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003724 else
3725 fprintf(output, "no target namespace");
3726 fprintf(output, "\n");
3727 if (schema->annot != NULL)
3728 xmlSchemaAnnotDump(output, schema->annot);
3729
3730 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3731 output);
3732 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003733 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003734}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003735
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003736#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003737/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003738 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003739 * @vctxt: the WXS validation context
3740 *
3741 * Displays the current IDC table for debug purposes.
3742 */
3743static void
3744xmlSchemaDebugDumpIDCTable(FILE * output,
3745 const xmlChar *namespaceName,
3746 const xmlChar *localName,
3747 xmlSchemaPSVIIDCBindingPtr bind)
3748{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003749 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003750 xmlSchemaPSVIIDCNodePtr tab;
3751 xmlSchemaPSVIIDCKeyPtr key;
3752 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003753
3754 fprintf(output, "IDC: TABLES on %s\n",
3755 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003756 FREE_AND_NULL(str)
3757
3758 if (bind == NULL)
3759 return;
3760 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003761 fprintf(output, "IDC: BINDING %s\n",
3762 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003763 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003764 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003765 for (i = 0; i < bind->nbNodes; i++) {
3766 tab = bind->nodeTable[i];
3767 fprintf(output, " ( ");
3768 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003769 key = tab->keys[j];
3770 if ((key != NULL) && (key->val != NULL)) {
3771 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003772 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003773 fprintf(output, "\"%s\" ", value);
3774 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003775 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003776 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003777 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003778 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003779 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003780 else
3781 fprintf(output, "(key missing), ");
3782 }
3783 fprintf(output, ")\n");
3784 }
3785 bind = bind->next;
3786 } while (bind != NULL);
3787}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003788#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003789#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003790
3791/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003792 * *
3793 * Utilities *
3794 * *
3795 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003796
Daniel Veillardc0826a72004-08-10 14:17:33 +00003797/**
3798 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003799 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003800 * @name: the name of the attribute
3801 *
3802 * Seeks an attribute with a name of @name in
3803 * no namespace.
3804 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003805 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003806 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003807static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003808xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003809{
3810 xmlAttrPtr prop;
3811
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003812 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003813 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003814 prop = node->properties;
3815 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003816 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003817 return(prop);
3818 prop = prop->next;
3819 }
3820 return (NULL);
3821}
3822
3823/**
3824 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003825 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003826 * @uri: the uri
3827 * @name: the name of the attribute
3828 *
3829 * Seeks an attribute with a local name of @name and
3830 * a namespace URI of @uri.
3831 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003832 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003833 */
3834static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003835xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003836{
3837 xmlAttrPtr prop;
3838
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003839 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003840 return(NULL);
3841 prop = node->properties;
3842 while (prop != NULL) {
3843 if ((prop->ns != NULL) &&
3844 xmlStrEqual(prop->name, BAD_CAST name) &&
3845 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003846 return(prop);
3847 prop = prop->next;
3848 }
3849 return (NULL);
3850}
3851
3852static const xmlChar *
3853xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3854{
3855 xmlChar *val;
3856 const xmlChar *ret;
3857
3858 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003859 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003860 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003861 ret = xmlDictLookup(ctxt->dict, val, -1);
3862 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003863 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003864}
3865
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003866/**
3867 * xmlSchemaGetProp:
3868 * @ctxt: the parser context
3869 * @node: the node
3870 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003871 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003872 * Read a attribute value and internalize the string
3873 *
3874 * Returns the string or NULL if not present.
3875 */
3876static const xmlChar *
3877xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3878 const char *name)
3879{
3880 xmlChar *val;
3881 const xmlChar *ret;
3882
3883 val = xmlGetProp(node, BAD_CAST name);
3884 if (val == NULL)
3885 return(NULL);
3886 ret = xmlDictLookup(ctxt->dict, val, -1);
3887 xmlFree(val);
3888 return(ret);
3889}
3890
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003891/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003892 * *
3893 * Parsing functions *
3894 * *
3895 ************************************************************************/
3896
3897/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003898 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003899 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003900 * @name: the element name
3901 * @ns: the element namespace
3902 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003903 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003904 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003905 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003906 */
3907static xmlSchemaElementPtr
3908xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003909 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003910{
3911 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003912
3913 if ((name == NULL) || (schema == NULL))
3914 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003915
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003916 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003917 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003918 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003919 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003920 } else
3921 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003922 /*
3923 * This one was removed, since top level element declarations have
3924 * the target namespace specified in targetNamespace of the <schema>
3925 * information element, even if elementFormDefault is "unqualified".
3926 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003927
William M. Bracke7091952004-05-11 15:09:58 +00003928 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003929 if (xmlStrEqual(namespace, schema->targetNamespace))
3930 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3931 else
3932 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003933 if ((ret != NULL) &&
3934 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003935 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003936 }
William M. Bracke7091952004-05-11 15:09:58 +00003937 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003938
William M. Brack2f2a6632004-08-20 23:09:47 +00003939 /*
3940 * Removed since imported components will be hold by the main schema only.
3941 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003942 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003943 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003944 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003945 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003946 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003947 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003948 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3949 return (ret);
3950 } else
3951 ret = NULL;
3952 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003953 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003954#ifdef DEBUG
3955 if (ret == NULL) {
3956 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003957 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003958 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003959 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003960 namespace);
3961 }
3962#endif
3963 return (ret);
3964}
3965
3966/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003967 * xmlSchemaGetType:
3968 * @schema: the schemas context
3969 * @name: the type name
3970 * @ns: the type namespace
3971 *
3972 * Lookup a type in the schemas or the predefined types
3973 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003974 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003975 */
3976static xmlSchemaTypePtr
3977xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003978 const xmlChar * namespace)
3979{
Daniel Veillard4255d502002-04-16 15:50:10 +00003980 xmlSchemaTypePtr ret;
3981
3982 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003983 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003984 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003985 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003986 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003987 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003988 }
3989 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003990 if (ret != NULL)
3991 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003992 /*
3993 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003994 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003995 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003996 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003997 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003998 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003999 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00004000 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004001 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4002 return (ret);
4003 } else
4004 ret = NULL;
4005 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004006 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004007#ifdef DEBUG
4008 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004009 if (namespace == NULL)
4010 fprintf(stderr, "Unable to lookup type %s", name);
4011 else
4012 fprintf(stderr, "Unable to lookup type %s:%s", name,
4013 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004014 }
4015#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004016 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004017}
4018
Daniel Veillard3646d642004-06-02 19:19:14 +00004019/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004020 * xmlSchemaGetAttributeDecl:
4021 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004022 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004023 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004024 *
4025 * Lookup a an attribute in the schema or imported schemas
4026 *
4027 * Returns the attribute declaration or NULL if not found.
4028 */
4029static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004030xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004031 const xmlChar * namespace)
4032{
4033 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004034
4035 if ((name == NULL) || (schema == NULL))
4036 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004037
4038
Daniel Veillard3646d642004-06-02 19:19:14 +00004039 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4040 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004041 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004042 else
4043 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004044 /*
4045 * Removed, since imported components will be hold by the main schema only.
4046 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004047 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004048 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004049 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004050 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004051 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004052 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004053 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4054 return (ret);
4055 } else
4056 ret = NULL;
4057 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004058 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004059#ifdef DEBUG
4060 if (ret == NULL) {
4061 if (namespace == NULL)
4062 fprintf(stderr, "Unable to lookup attribute %s", name);
4063 else
4064 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4065 namespace);
4066 }
4067#endif
4068 return (ret);
4069}
4070
4071/**
4072 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004073 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004074 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004075 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004076 *
4077 * Lookup a an attribute group in the schema or imported schemas
4078 *
4079 * Returns the attribute group definition or NULL if not found.
4080 */
4081static xmlSchemaAttributeGroupPtr
4082xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4083 const xmlChar * namespace)
4084{
4085 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004086
4087 if ((name == NULL) || (schema == NULL))
4088 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004089
4090
Daniel Veillard3646d642004-06-02 19:19:14 +00004091 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4092 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004093 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004094 else
4095 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004096 /*
4097 * Removed since imported components will be hold by the main schema only.
4098 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004099 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004100 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004101 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004102 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004103 if (import != NULL) {
4104 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4105 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4106 return (ret);
4107 else
4108 ret = NULL;
4109 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004110 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004111#ifdef DEBUG
4112 if (ret == NULL) {
4113 if (namespace == NULL)
4114 fprintf(stderr, "Unable to lookup attribute group %s", name);
4115 else
4116 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4117 namespace);
4118 }
4119#endif
4120 return (ret);
4121}
4122
4123/**
4124 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004125 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004126 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004127 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004128 *
4129 * Lookup a group in the schema or imported schemas
4130 *
4131 * Returns the group definition or NULL if not found.
4132 */
4133static xmlSchemaTypePtr
4134xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4135 const xmlChar * namespace)
4136{
4137 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004138
4139 if ((name == NULL) || (schema == NULL))
4140 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004141
Daniel Veillard3646d642004-06-02 19:19:14 +00004142 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004143 /*
4144 * Removed since imported components will be hold by the main schema only.
4145 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004146 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004147 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004148 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004149 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004150 if (import != NULL) {
4151 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4152 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4153 return (ret);
4154 else
4155 ret = NULL;
4156 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004157 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004158#ifdef DEBUG
4159 if (ret == NULL) {
4160 if (namespace == NULL)
4161 fprintf(stderr, "Unable to lookup group %s", name);
4162 else
4163 fprintf(stderr, "Unable to lookup group %s:%s", name,
4164 namespace);
4165 }
4166#endif
4167 return (ret);
4168}
4169
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004170/**
4171 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004172 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004173 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004174 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004175 *
4176 * Lookup a group in the schema or imported schemas
4177 *
4178 * Returns the group definition or NULL if not found.
4179 */
4180static xmlSchemaTreeItemPtr
4181xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4182 xmlSchemaTypeType itemType,
4183 const xmlChar *name,
4184 const xmlChar *targetNs)
4185{
4186 switch (itemType) {
4187 case XML_SCHEMA_TYPE_GROUP:
4188 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4189 name, targetNs));
4190 case XML_SCHEMA_TYPE_ELEMENT:
4191 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4192 name, targetNs));
4193 default:
4194 return (NULL);
4195 }
4196}
4197
Daniel Veillard4255d502002-04-16 15:50:10 +00004198/************************************************************************
4199 * *
4200 * Parsing functions *
4201 * *
4202 ************************************************************************/
4203
4204#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004205 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004206
4207/**
4208 * xmlSchemaIsBlank:
4209 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004210 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004211 *
4212 * Check if a string is ignorable
4213 *
4214 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4215 */
4216static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004217xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004218{
Daniel Veillard4255d502002-04-16 15:50:10 +00004219 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004220 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004221 if (len < 0) {
4222 while (*str != 0) {
4223 if (!(IS_BLANK_CH(*str)))
4224 return (0);
4225 str++;
4226 }
4227 } else while ((*str != 0) && (len != 0)) {
4228 if (!(IS_BLANK_CH(*str)))
4229 return (0);
4230 str++;
4231 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004232 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004233
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004234 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004235}
4236
4237/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004238 * xmlSchemaAddAssembledItem:
4239 * @ctxt: a schema parser context
4240 * @schema: the schema being built
4241 * @item: the item
4242 *
4243 * Add a item to the schema's list of current items.
4244 * This is used if the schema was already constructed and
4245 * new schemata need to be added to it.
4246 * *WARNING* this interface is highly subject to change.
4247 *
4248 * Returns 0 if suceeds and -1 if an internal error occurs.
4249 */
4250static int
4251xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4252 xmlSchemaTypePtr item)
4253{
4254 static int growSize = 100;
4255 xmlSchemaAssemblePtr ass;
4256
4257 ass = ctxt->assemble;
4258 if (ass->sizeItems < 0) {
4259 /* If disabled. */
4260 return (0);
4261 }
4262 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004263 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004264 if (ass->items == NULL) {
4265 xmlSchemaPErrMemory(ctxt,
4266 "allocating new item buffer", NULL);
4267 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004268 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004269 ass->sizeItems = growSize;
4270 } else if (ass->sizeItems <= ass->nbItems) {
4271 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004272 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004273 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4274 if (ass->items == NULL) {
4275 xmlSchemaPErrMemory(ctxt,
4276 "growing item buffer", NULL);
4277 ass->sizeItems = 0;
4278 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004279 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004280 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004281 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004282 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4283 return (0);
4284}
4285
4286/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004287 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004288 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004289 * @schema: the schema being built
4290 * @name: the item name
4291 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004292 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004293 * *WARNING* this interface is highly subject to change
4294 *
4295 * Returns the new struture or NULL in case of error
4296 */
4297static xmlSchemaNotationPtr
4298xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004299 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004300{
4301 xmlSchemaNotationPtr ret = NULL;
4302 int val;
4303
4304 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4305 return (NULL);
4306
4307 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004308 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004309 if (schema->notaDecl == NULL)
4310 return (NULL);
4311
4312 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4313 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004314 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004315 return (NULL);
4316 }
4317 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004318 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004319 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4320 ret);
4321 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004322 /*
4323 * TODO: This should never happen, since a unique name will be computed.
4324 * If it fails, then an other internal error must have occured.
4325 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004326 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4327 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004328 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004329 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004330 xmlFree(ret);
4331 return (NULL);
4332 }
4333 return (ret);
4334}
4335
4336
4337/**
4338 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004339 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004340 * @schema: the schema being built
4341 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004342 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004343 *
4344 * Add an XML schema Attrribute declaration
4345 * *WARNING* this interface is highly subject to change
4346 *
4347 * Returns the new struture or NULL in case of error
4348 */
4349static xmlSchemaAttributePtr
4350xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004351 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004352 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004353{
4354 xmlSchemaAttributePtr ret = NULL;
4355 int val;
4356
4357 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4358 return (NULL);
4359
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004360#ifdef DEBUG
4361 fprintf(stderr, "Adding attribute %s\n", name);
4362 if (namespace != NULL)
4363 fprintf(stderr, " target namespace %s\n", namespace);
4364#endif
4365
Daniel Veillard4255d502002-04-16 15:50:10 +00004366 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004367 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004368 if (schema->attrDecl == NULL)
4369 return (NULL);
4370
4371 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4372 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004373 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004374 return (NULL);
4375 }
4376 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004377 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004378 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004379 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004380 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004381 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004382 if (topLevel) {
4383 xmlSchemaPCustomErr(ctxt,
4384 XML_SCHEMAP_REDEFINED_ATTR,
4385 NULL, NULL, node,
4386 "A global attribute declaration with the name '%s' does "
4387 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004388 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004389 return (NULL);
4390 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004391 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004392 /*
4393 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4394 * in the scenario:
4395 * 1. multiple top-level complex types have different target
4396 * namespaces but have the SAME NAME; this can happen if
4397 * schemata are imported
4398 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004399 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004400 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004401 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004402 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004403 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004404 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004405
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004406 if (val != 0) {
4407 xmlSchemaPCustomErr(ctxt,
4408 XML_SCHEMAP_INTERNAL,
4409 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004410 "Internal error: xmlSchemaAddAttribute, "
4411 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004412 "could not be added to the hash.", name);
4413 xmlFree(ret);
4414 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004415 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004416 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004417 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004418 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004419 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004420 return (ret);
4421}
4422
4423/**
4424 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004425 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004426 * @schema: the schema being built
4427 * @name: the item name
4428 *
4429 * Add an XML schema Attrribute Group declaration
4430 *
4431 * Returns the new struture or NULL in case of error
4432 */
4433static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004434xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004435 xmlSchemaPtr schema, const xmlChar * name,
4436 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004437{
4438 xmlSchemaAttributeGroupPtr ret = NULL;
4439 int val;
4440
4441 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4442 return (NULL);
4443
4444 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004445 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 if (schema->attrgrpDecl == NULL)
4447 return (NULL);
4448
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004449 ret =
4450 (xmlSchemaAttributeGroupPtr)
4451 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004452 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004453 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004454 return (NULL);
4455 }
4456 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004457 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004459 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004460 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004461 xmlSchemaPCustomErr(ctxt,
4462 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4463 NULL, NULL, node,
4464 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004465 xmlFree(ret);
4466 return (NULL);
4467 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004468 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004469 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004470 return (ret);
4471}
4472
4473/**
4474 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004475 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004476 * @schema: the schema being built
4477 * @name: the type name
4478 * @namespace: the type namespace
4479 *
4480 * Add an XML schema Element declaration
4481 * *WARNING* this interface is highly subject to change
4482 *
4483 * Returns the new struture or NULL in case of error
4484 */
4485static xmlSchemaElementPtr
4486xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004487 const xmlChar * name, const xmlChar * namespace,
4488 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004489{
4490 xmlSchemaElementPtr ret = NULL;
4491 int val;
4492
4493 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4494 return (NULL);
4495
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004496#ifdef DEBUG
4497 fprintf(stderr, "Adding element %s\n", name);
4498 if (namespace != NULL)
4499 fprintf(stderr, " target namespace %s\n", namespace);
4500#endif
4501
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004503 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004504 if (schema->elemDecl == NULL)
4505 return (NULL);
4506
4507 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4508 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004509 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004510 return (NULL);
4511 }
4512 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004513 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004514 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004515 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004516 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004517 if (topLevel) {
4518 xmlSchemaPCustomErr(ctxt,
4519 XML_SCHEMAP_REDEFINED_ELEMENT,
4520 NULL, NULL, node,
4521 "A global element declaration with the name '%s' does "
4522 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004523 xmlFree(ret);
4524 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004525 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004526 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004527
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004528 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004529 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004530 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004531 if (val != 0) {
4532 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004533 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004534 NULL, NULL, node,
4535 "Internal error: xmlSchemaAddElement, "
4536 "a dublicate element declaration with the name '%s' "
4537 "could not be added to the hash.", name);
4538 xmlFree(ret);
4539 return (NULL);
4540 }
4541 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004542
Daniel Veillard4255d502002-04-16 15:50:10 +00004543 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004544 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004545 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004546 return (ret);
4547}
4548
4549/**
4550 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004551 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004552 * @schema: the schema being built
4553 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004554 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004555 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004556 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004557 * *WARNING* this interface is highly subject to change
4558 *
4559 * Returns the new struture or NULL in case of error
4560 */
4561static xmlSchemaTypePtr
4562xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004563 const xmlChar * name, const xmlChar * namespace,
4564 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004565{
4566 xmlSchemaTypePtr ret = NULL;
4567 int val;
4568
4569 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4570 return (NULL);
4571
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004572#ifdef DEBUG
4573 fprintf(stderr, "Adding type %s\n", name);
4574 if (namespace != NULL)
4575 fprintf(stderr, " target namespace %s\n", namespace);
4576#endif
4577
Daniel Veillard4255d502002-04-16 15:50:10 +00004578 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004579 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004580 if (schema->typeDecl == NULL)
4581 return (NULL);
4582
4583 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4584 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004585 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004586 return (NULL);
4587 }
4588 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004589 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004590 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004591 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004592 if (val != 0) {
4593 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004594 xmlSchemaPCustomErr(ctxt,
4595 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004596 NULL, NULL, node,
4597 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004598 xmlFree(ret);
4599 return (NULL);
4600 } else {
4601 xmlSchemaTypePtr prev;
4602
4603 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4604 if (prev == NULL) {
4605 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004606 XML_ERR_INTERNAL_ERROR,
4607 "Internal error: xmlSchemaAddType, on type "
4608 "'%s'.\n",
4609 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004610 xmlFree(ret);
4611 return (NULL);
4612 }
4613 ret->redef = prev->redef;
4614 prev->redef = ret;
4615 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004616 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004617 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004618 ret->minOccurs = 1;
4619 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004620 ret->attributeUses = NULL;
4621 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004622 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004623 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004624 return (ret);
4625}
4626
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004627static xmlSchemaQNameRefPtr
4628xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4629 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004630 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004631 const xmlChar *refNs)
4632{
4633 xmlSchemaQNameRefPtr ret;
4634
4635 ret = (xmlSchemaQNameRefPtr)
4636 xmlMalloc(sizeof(xmlSchemaQNameRef));
4637 if (ret == NULL) {
4638 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4639 NULL);
4640 return (NULL);
4641 }
4642 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4643 ret->name = refName;
4644 ret->targetNamespace = refNs;
4645 ret->item = NULL;
4646 ret->itemType = refType;
4647 /*
4648 * Store the reference item in the schema.
4649 */
4650 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4651 return (ret);
4652}
4653
4654/**
4655 * xmlSchemaAddModelGroup:
4656 * @ctxt: a schema parser context
4657 * @schema: the schema being built
4658 * @type: the "compositor" type of the model group
4659 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004660 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004661 *
4662 * Adds a schema model group
4663 * *WARNING* this interface is highly subject to change
4664 *
4665 * Returns the new struture or NULL in case of error
4666 */
4667static xmlSchemaModelGroupPtr
4668xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4669 xmlSchemaTypeType type, const xmlChar **container,
4670 xmlNodePtr node)
4671{
4672 xmlSchemaModelGroupPtr ret = NULL;
4673 xmlChar buf[30];
4674
4675 if ((ctxt == NULL) || (schema == NULL))
4676 return (NULL);
4677
4678#ifdef DEBUG
4679 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004680#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004681 ret = (xmlSchemaModelGroupPtr)
4682 xmlMalloc(sizeof(xmlSchemaModelGroup));
4683 if (ret == NULL) {
4684 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4685 NULL);
4686 return (NULL);
4687 }
4688 ret->type = type;
4689 ret->annot = NULL;
4690 ret->node = node;
4691 ret->children = NULL;
4692 ret->next = NULL;
4693 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4694 if (container != NULL)
4695 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4696 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004697 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004698 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4699 } else {
4700 if (container != NULL)
4701 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4702 }
4703 if (container != NULL)
4704 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4705 /*
4706 * Add to volatile items.
4707 * TODO: this should be changed someday.
4708 */
4709 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4710 xmlFree(ret);
4711 return (NULL);
4712 }
4713 return (ret);
4714}
4715
4716
4717/**
4718 * xmlSchemaAddParticle:
4719 * @ctxt: a schema parser context
4720 * @schema: the schema being built
4721 * @node: the corresponding node in the schema doc
4722 * @min: the minOccurs
4723 * @max: the maxOccurs
4724 *
4725 * Adds an XML schema particle component.
4726 * *WARNING* this interface is highly subject to change
4727 *
4728 * Returns the new struture or NULL in case of error
4729 */
4730static xmlSchemaParticlePtr
4731xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4732 xmlNodePtr node, int min, int max)
4733{
4734 xmlSchemaParticlePtr ret = NULL;
4735 if ((ctxt == NULL) || (schema == NULL))
4736 return (NULL);
4737
4738#ifdef DEBUG
4739 fprintf(stderr, "Adding particle component\n");
4740#endif
4741 ret = (xmlSchemaParticlePtr)
4742 xmlMalloc(sizeof(xmlSchemaParticle));
4743 if (ret == NULL) {
4744 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4745 NULL);
4746 return (NULL);
4747 }
4748 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4749 ret->annot = NULL;
4750 ret->node = node;
4751 ret->minOccurs = min;
4752 ret->maxOccurs = max;
4753 ret->next = NULL;
4754 ret->children = NULL;
4755
4756 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4757 xmlFree(ret);
4758 return (NULL);
4759 }
4760 return (ret);
4761}
4762
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004763/**
4764 * xmlSchemaAddGroup:
4765 * @ctxt: a schema validation context
4766 * @schema: the schema being built
4767 * @name: the group name
4768 *
4769 * Add an XML schema Group definition
4770 *
4771 * Returns the new struture or NULL in case of error
4772 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004773static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004774xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004775 const xmlChar *name, const xmlChar *namespaceName,
4776 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004777{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004778 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004779 int val;
4780
4781 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4782 return (NULL);
4783
4784 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004785 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004786 if (schema->groupDecl == NULL)
4787 return (NULL);
4788
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004789 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004790 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004791 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004792 return (NULL);
4793 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004794 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004795 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004796 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004797 ret->node = node;
4798 ret->targetNamespace = namespaceName;
4799 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004800 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004801 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004802 XML_SCHEMAP_REDEFINED_GROUP,
4803 NULL, NULL, node,
4804 "A global model group definition with the name '%s' does already "
4805 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004806 xmlFree(ret);
4807 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004808 }
4809 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004810 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004811 return (ret);
4812}
4813
Daniel Veillard3646d642004-06-02 19:19:14 +00004814/**
4815 * xmlSchemaNewWildcardNs:
4816 * @ctxt: a schema validation context
4817 *
4818 * Creates a new wildcard namespace constraint.
4819 *
4820 * Returns the new struture or NULL in case of error
4821 */
4822static xmlSchemaWildcardNsPtr
4823xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4824{
4825 xmlSchemaWildcardNsPtr ret;
4826
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004827 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004828 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4829 if (ret == NULL) {
4830 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004831 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004832 }
4833 ret->value = NULL;
4834 ret->next = NULL;
4835 return (ret);
4836}
4837
4838/**
4839 * xmlSchemaAddWildcard:
4840 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004841 * @schema: a schema
4842 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004843 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004844 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004845 *
4846 * Returns the new struture or NULL in case of error
4847 */
4848static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004849xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4850 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004851{
4852 xmlSchemaWildcardPtr ret = NULL;
4853
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004854 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004855 return (NULL);
4856
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004857#ifdef DEBUG
4858 fprintf(stderr, "Adding wildcard component\n");
4859#endif
4860
Daniel Veillard3646d642004-06-02 19:19:14 +00004861 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4862 if (ret == NULL) {
4863 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4864 return (NULL);
4865 }
4866 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004867 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004868 ret->minOccurs = 1;
4869 ret->maxOccurs = 1;
4870
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004871 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4872 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4873 "Failed to add a wildcard component to the list", NULL);
4874 xmlFree(ret);
4875 return (NULL);
4876 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004877 return (ret);
4878}
4879
Daniel Veillard4255d502002-04-16 15:50:10 +00004880/************************************************************************
4881 * *
4882 * Utilities for parsing *
4883 * *
4884 ************************************************************************/
4885
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004886#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004887/**
4888 * xmlGetQNameProp:
4889 * @ctxt: a schema validation context
4890 * @node: a subtree containing XML Schema informations
4891 * @name: the attribute name
4892 * @namespace: the result namespace if any
4893 *
4894 * Extract a QName Attribute value
4895 *
4896 * Returns the NCName or NULL if not found, and also update @namespace
4897 * with the namespace URI
4898 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004899static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004900xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004901 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004902{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004903 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004904 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004905 const xmlChar *ret, *prefix;
4906 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004907 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004908
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004909 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004910 attr = xmlSchemaGetPropNode(node, name);
4911 if (attr == NULL)
4912 return (NULL);
4913 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004914
Daniel Veillard4255d502002-04-16 15:50:10 +00004915 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004916 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004917
Daniel Veillardba0153a2004-04-01 10:42:31 +00004918 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004919 ns = xmlSearchNs(node->doc, node, 0);
4920 if (ns) {
4921 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4922 return (val);
4923 }
4924 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004925 ret = xmlSplitQName3(val, &len);
4926 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004927 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004928 }
4929 ret = xmlDictLookup(ctxt->dict, ret, -1);
4930 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004931
4932 ns = xmlSearchNs(node->doc, node, prefix);
4933 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004934 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4935 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004936 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004937 "The QName value '%s' has no corresponding namespace "
4938 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004939 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004940 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004941 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004942 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004943}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004944#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004945
4946/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004947 * xmlSchemaPValAttrNodeQNameValue:
4948 * @ctxt: a schema parser context
4949 * @schema: the schema context
4950 * @ownerDes: the designation of the parent element
4951 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004952 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004953 * @local: the resulting local part if found, the attribute value otherwise
4954 * @uri: the resulting namespace URI if found
4955 *
4956 * Extracts the local name and the URI of a QName value and validates it.
4957 * This one is intended to be used on attribute values that
4958 * should resolve to schema components.
4959 *
4960 * Returns 0, in case the QName is valid, a positive error code
4961 * if not valid and -1 if an internal error occurs.
4962 */
4963static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004964xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004965 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004966 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004967 xmlSchemaTypePtr ownerItem,
4968 xmlAttrPtr attr,
4969 const xmlChar *value,
4970 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004971 const xmlChar **local)
4972{
4973 const xmlChar *pref;
4974 xmlNsPtr ns;
4975 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004976
Daniel Veillardc0826a72004-08-10 14:17:33 +00004977 *uri = NULL;
4978 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004979 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004980 if (ret > 0) {
4981 xmlSchemaPSimpleTypeErr(ctxt,
4982 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4983 ownerItem, (xmlNodePtr) attr,
4984 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4985 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004986 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004987 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004988 } else if (ret < 0)
4989 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004990
4991 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004992 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4993 if (ns)
4994 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4995 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4996 /*
4997 * This one takes care of included schemas with no
4998 * target namespace.
4999 */
5000 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005001 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005002 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005003 return (0);
5004 }
5005 /*
5006 * At this point xmlSplitQName3 has to return a local name.
5007 */
5008 *local = xmlSplitQName3(value, &len);
5009 *local = xmlDictLookup(ctxt->dict, *local, -1);
5010 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005011 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5012 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005013 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005014 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005015 ownerItem, (xmlNodePtr) attr,
5016 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5017 "The value '%s' of simple type 'xs:QName' has no "
5018 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005019 return (ctxt->err);
5020 } else {
5021 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005022 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005023 return (0);
5024}
5025
5026/**
5027 * xmlSchemaPValAttrNodeQName:
5028 * @ctxt: a schema parser context
5029 * @schema: the schema context
5030 * @ownerDes: the designation of the owner element
5031 * @ownerItem: the owner as a schema object
5032 * @attr: the attribute node
5033 * @local: the resulting local part if found, the attribute value otherwise
5034 * @uri: the resulting namespace URI if found
5035 *
5036 * Extracts and validates the QName of an attribute value.
5037 * This one is intended to be used on attribute values that
5038 * should resolve to schema components.
5039 *
5040 * Returns 0, in case the QName is valid, a positive error code
5041 * if not valid and -1 if an internal error occurs.
5042 */
5043static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005044xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005045 xmlSchemaPtr schema,
5046 xmlChar **ownerDes,
5047 xmlSchemaTypePtr ownerItem,
5048 xmlAttrPtr attr,
5049 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005050 const xmlChar **local)
5051{
5052 const xmlChar *value;
5053
5054 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005055 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5056 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005057}
5058
5059/**
5060 * xmlSchemaPValAttrQName:
5061 * @ctxt: a schema parser context
5062 * @schema: the schema context
5063 * @ownerDes: the designation of the parent element
5064 * @ownerItem: the owner as a schema object
5065 * @ownerElem: the parent node of the attribute
5066 * @name: the name of the attribute
5067 * @local: the resulting local part if found, the attribute value otherwise
5068 * @uri: the resulting namespace URI if found
5069 *
5070 * Extracts and validates the QName of an attribute value.
5071 *
5072 * Returns 0, in case the QName is valid, a positive error code
5073 * if not valid and -1 if an internal error occurs.
5074 */
5075static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005076xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5077 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005078 xmlChar **ownerDes,
5079 xmlSchemaTypePtr ownerItem,
5080 xmlNodePtr ownerElem,
5081 const char *name,
5082 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005083 const xmlChar **local)
5084{
5085 xmlAttrPtr attr;
5086
5087 attr = xmlSchemaGetPropNode(ownerElem, name);
5088 if (attr == NULL) {
5089 *local = NULL;
5090 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005091 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005092 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005093 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5094 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005095}
5096
5097/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005098 * xmlSchemaPValAttrID:
5099 * @ctxt: a schema parser context
5100 * @schema: the schema context
5101 * @ownerDes: the designation of the parent element
5102 * @ownerItem: the owner as a schema object
5103 * @ownerElem: the parent node of the attribute
5104 * @name: the name of the attribute
5105 *
5106 * Extracts and validates the ID of an attribute value.
5107 *
5108 * Returns 0, in case the ID is valid, a positive error code
5109 * if not valid and -1 if an internal error occurs.
5110 */
5111static int
5112xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005113 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005114 xmlSchemaTypePtr ownerItem,
5115 xmlNodePtr ownerElem,
5116 const xmlChar *name)
5117{
5118 int ret;
5119 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005120 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005121
5122 value = xmlGetNoNsProp(ownerElem, name);
5123 if (value == NULL)
5124 return (0);
5125
5126 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5127 if (attr == NULL)
5128 return (-1);
5129
5130 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005131 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005132 /*
5133 * NOTE: the IDness might have already be declared in the DTD
5134 */
5135 if (attr->atype != XML_ATTRIBUTE_ID) {
5136 xmlIDPtr res;
5137 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005138
5139 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005140 * TODO: Use xmlSchemaStrip here; it's not exported at this
5141 * moment.
5142 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005143 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005144 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005145 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005146 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5147 if (res == NULL) {
5148 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005149 xmlSchemaPSimpleTypeErr(ctxt,
5150 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5151 ownerItem, (xmlNodePtr) attr,
5152 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5153 NULL, NULL, "Duplicate value '%s' of simple "
5154 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005155 } else
5156 attr->atype = XML_ATTRIBUTE_ID;
5157 if (strip != NULL)
5158 xmlFree(strip);
5159 }
5160 } else if (ret > 0) {
5161 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005162 xmlSchemaPSimpleTypeErr(ctxt,
5163 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5164 ownerItem, (xmlNodePtr) attr,
5165 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5166 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5167 "not a valid 'xs:NCName'",
5168 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005169 }
5170 xmlFree(value);
5171
5172 return (ret);
5173}
5174
5175/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005176 * xmlGetMaxOccurs:
5177 * @ctxt: a schema validation context
5178 * @node: a subtree containing XML Schema informations
5179 *
5180 * Get the maxOccurs property
5181 *
5182 * Returns the default if not found, or the value
5183 */
5184static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005185xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5186 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005187{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005188 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005189 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005190 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005191
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005192 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5193 if (attr == NULL)
5194 return (def);
5195 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005196
5197 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005198 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005199 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005200 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5201 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005202 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005203 val, NULL, NULL, NULL);
5204 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005205 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005206 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005207 }
5208
5209 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005210 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005211 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005212 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005213 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005214 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5215 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005216 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005217 val, NULL, NULL, NULL);
5218 return (def);
5219 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005220 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005221 ret = ret * 10 + (*cur - '0');
5222 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005223 }
William M. Brack76e95df2003-10-18 16:20:14 +00005224 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005225 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005226 /*
5227 * TODO: Restrict the maximal value to Integer.
5228 */
5229 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005230 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005231 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5232 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005233 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005234 val, NULL, NULL, NULL);
5235 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005236 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005237 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005238}
5239
5240/**
5241 * xmlGetMinOccurs:
5242 * @ctxt: a schema validation context
5243 * @node: a subtree containing XML Schema informations
5244 *
5245 * Get the minOccurs property
5246 *
5247 * Returns the default if not found, or the value
5248 */
5249static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005250xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005251 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005252{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005253 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005254 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005255 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005256
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005257 attr = xmlSchemaGetPropNode(node, "minOccurs");
5258 if (attr == NULL)
5259 return (def);
5260 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005261 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005262 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005263 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005264 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005265 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005266 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5267 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005268 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005269 val, NULL, NULL, NULL);
5270 return (def);
5271 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005272 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005273 ret = ret * 10 + (*cur - '0');
5274 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005275 }
William M. Brack76e95df2003-10-18 16:20:14 +00005276 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005277 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005278 /*
5279 * TODO: Restrict the maximal value to Integer.
5280 */
5281 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005282 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005283 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5284 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005285 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005286 val, NULL, NULL, NULL);
5287 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005288 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005289 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005290}
5291
5292/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005293 * xmlSchemaPGetBoolNodeValue:
5294 * @ctxt: a schema validation context
5295 * @ownerDes: owner designation
5296 * @ownerItem: the owner as a schema item
5297 * @node: the node holding the value
5298 *
5299 * Converts a boolean string value into 1 or 0.
5300 *
5301 * Returns 0 or 1.
5302 */
5303static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005304xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5305 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005306 xmlSchemaTypePtr ownerItem,
5307 xmlNodePtr node)
5308{
5309 xmlChar *value = NULL;
5310 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005311
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005312 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005313 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005314 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005315 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005316 * can have the following legal literals {true, false, 1, 0}.
5317 */
5318 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5319 res = 1;
5320 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5321 res = 0;
5322 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5323 res = 1;
5324 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005325 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005326 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005327 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005328 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005329 ownerItem, node,
5330 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5331 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005332 NULL, NULL, NULL);
5333 }
5334 if (value != NULL)
5335 xmlFree(value);
5336 return (res);
5337}
5338
5339/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005340 * xmlGetBooleanProp:
5341 * @ctxt: a schema validation context
5342 * @node: a subtree containing XML Schema informations
5343 * @name: the attribute name
5344 * @def: the default value
5345 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005346 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005347 *
5348 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005349 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005350 */
5351static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005352xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5353 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005354 xmlSchemaTypePtr ownerItem,
5355 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005356 const char *name, int def)
5357{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005358 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005359
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005360 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005361 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005362 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005363 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005364 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005365 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005366 * can have the following legal literals {true, false, 1, 0}.
5367 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005368 if (xmlStrEqual(val, BAD_CAST "true"))
5369 def = 1;
5370 else if (xmlStrEqual(val, BAD_CAST "false"))
5371 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005372 else if (xmlStrEqual(val, BAD_CAST "1"))
5373 def = 1;
5374 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005375 def = 0;
5376 else {
5377 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005378 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005379 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005380 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005381 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5382 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005383 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005384 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005385}
5386
5387/************************************************************************
5388 * *
5389 * Shema extraction from an Infoset *
5390 * *
5391 ************************************************************************/
5392static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5393 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005394 xmlNodePtr node,
5395 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005396static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5397 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005398 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005399 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005400 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005401static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5402 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005403 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005404 xmlNodePtr node,
5405 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005406static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5407 ctxt,
5408 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005409 xmlNodePtr node,
5410 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005411static xmlSchemaAttributeGroupPtr
5412xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005413 xmlSchemaPtr schema, xmlNodePtr node,
5414 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005415static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5416 xmlSchemaPtr schema,
5417 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005418static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005419xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5420 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005421
5422/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005423 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005424 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005425 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005426 * @ownerDes: the designation of the parent element
5427 * @ownerItem: the schema object owner if existent
5428 * @attr: the schema attribute node being validated
5429 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005430 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005431 *
5432 * Validates a value against the given built-in type.
5433 * This one is intended to be used internally for validation
5434 * of schema attribute values during parsing of the schema.
5435 *
5436 * Returns 0 if the value is valid, a positive error code
5437 * number otherwise and -1 in case of an internal or API error.
5438 */
5439static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005440xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5441 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5442 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005443 xmlAttrPtr attr,
5444 const xmlChar *value,
5445 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005446{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005447
5448 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005449
5450 /*
5451 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5452 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005453 */
5454 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005455 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005456 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5457 PERROR_INT("xmlSchemaPValAttrNodeValue",
5458 "the given type is not a built-in type");
5459 return (-1);
5460 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005461 switch (type->builtInType) {
5462 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005463 case XML_SCHEMAS_QNAME:
5464 case XML_SCHEMAS_ANYURI:
5465 case XML_SCHEMAS_TOKEN:
5466 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005467 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5468 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005469 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005470 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005471 PERROR_INT("xmlSchemaPValAttrNodeValue",
5472 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005473 return (-1);
5474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005475 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005476 /*
5477 * TODO: Should we use the S4S error codes instead?
5478 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005479 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005480 PERROR_INT("xmlSchemaPValAttrNodeValue",
5481 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005482 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005483 } else if (ret > 0) {
5484 if (VARIETY_LIST(type))
5485 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5486 else
5487 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5488 xmlSchemaPSimpleTypeErr(pctxt,
5489 ret, ownerItem, (xmlNodePtr) attr,
5490 type, NULL, value, NULL, NULL, NULL);
5491 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005492 return (ret);
5493}
5494
5495/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005496 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005497 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005498 * @ctxt: a schema parser context
5499 * @ownerDes: the designation of the parent element
5500 * @ownerItem: the schema object owner if existent
5501 * @attr: the schema attribute node being validated
5502 * @type: the built-in type to be validated against
5503 * @value: the resulting value if any
5504 *
5505 * Extracts and validates a value against the given built-in type.
5506 * This one is intended to be used internally for validation
5507 * of schema attribute values during parsing of the schema.
5508 *
5509 * Returns 0 if the value is valid, a positive error code
5510 * number otherwise and -1 in case of an internal or API error.
5511 */
5512static int
5513xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5514 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005515 xmlSchemaTypePtr ownerItem,
5516 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005517 xmlSchemaTypePtr type,
5518 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005519{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005520 const xmlChar *val;
5521
5522 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005523 return (-1);
5524
Daniel Veillardc0826a72004-08-10 14:17:33 +00005525 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5526 if (value != NULL)
5527 *value = val;
5528
5529 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005530 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005531}
5532
5533/**
5534 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005535 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005536 * @ctxt: a schema parser context
5537 * @node: the element node of the attribute
5538 * @ownerDes: the designation of the parent element
5539 * @ownerItem: the schema object owner if existent
5540 * @ownerElem: the owner element node
5541 * @name: the name of the schema attribute node
5542 * @type: the built-in type to be validated against
5543 * @value: the resulting value if any
5544 *
5545 * Extracts and validates a value against the given built-in type.
5546 * This one is intended to be used internally for validation
5547 * of schema attribute values during parsing of the schema.
5548 *
5549 * Returns 0 if the value is valid, a positive error code
5550 * number otherwise and -1 in case of an internal or API error.
5551 */
5552static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005553xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005554 xmlChar **ownerDes,
5555 xmlSchemaTypePtr ownerItem,
5556 xmlNodePtr ownerElem,
5557 const char *name,
5558 xmlSchemaTypePtr type,
5559 const xmlChar **value)
5560{
5561 xmlAttrPtr attr;
5562
5563 if ((ctxt == NULL) || (type == NULL)) {
5564 if (value != NULL)
5565 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005566 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005567 }
5568 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5569 if (value != NULL)
5570 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005571 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005572 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005573 "Internal error: xmlSchemaPValAttr, the given "
5574 "type '%s' is not a built-in type.\n",
5575 type->name, NULL);
5576 return (-1);
5577 }
5578 attr = xmlSchemaGetPropNode(ownerElem, name);
5579 if (attr == NULL) {
5580 if (value != NULL)
5581 *value = NULL;
5582 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005583 }
5584 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005585 type, value));
5586}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005587
5588static int
5589xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5590 xmlSchemaPtr schema,
5591 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005592 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005593 const xmlChar *namespaceName)
5594{
5595 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005596 return (1);
5597 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5598 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005599 if (pctxt->localImports != NULL) {
5600 int i;
5601 for (i = 0; i < pctxt->nbLocalImports; i++)
5602 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5603 return (1);
5604 }
5605 if (namespaceName == NULL)
5606 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005607 NULL, (xmlSchemaTypePtr) item, node,
5608 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005609 "namespace are not valid, since not indicated by an import "
5610 "statement", NULL);
5611 else
5612 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005613 NULL, (xmlSchemaTypePtr) item, node,
5614 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005615 "namespace '%s' are not valid, since not indicated by an import "
5616 "statement", namespaceName);
5617 return (0);
5618}
5619
Daniel Veillardc0826a72004-08-10 14:17:33 +00005620/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005621 * xmlSchemaParseAttrDecls:
5622 * @ctxt: a schema validation context
5623 * @schema: the schema being built
5624 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005625 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005626 *
5627 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005628 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005629 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5630 */
5631static xmlNodePtr
5632xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5633 xmlNodePtr child, xmlSchemaTypePtr type)
5634{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005635 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005636
Daniel Veillard4255d502002-04-16 15:50:10 +00005637 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005638 (IS_SCHEMA(child, "attributeGroup"))) {
5639 attr = NULL;
5640 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005641 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005642 } else if (IS_SCHEMA(child, "attributeGroup")) {
5643 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005644 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005645 }
5646 if (attr != NULL) {
5647 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005648 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5649 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5650 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005651 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005652 lastattr = attr;
5653 } else {
5654 lastattr->next = attr;
5655 lastattr = attr;
5656 }
5657 }
5658 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005659 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005660 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005661}
5662
5663/**
5664 * xmlSchemaParseAnnotation:
5665 * @ctxt: a schema validation context
5666 * @schema: the schema being built
5667 * @node: a subtree containing XML Schema informations
5668 *
5669 * parse a XML schema Attrribute declaration
5670 * *WARNING* this interface is highly subject to change
5671 *
William M. Bracke7091952004-05-11 15:09:58 +00005672 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005673 * 1 in case of success.
5674 */
5675static xmlSchemaAnnotPtr
5676xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5677 xmlNodePtr node)
5678{
5679 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005680 xmlNodePtr child = NULL;
5681 xmlAttrPtr attr;
5682 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005683
Daniel Veillardc0826a72004-08-10 14:17:33 +00005684 /*
5685 * INFO: S4S completed.
5686 */
5687 /*
5688 * id = ID
5689 * {any attributes with non-schema namespace . . .}>
5690 * Content: (appinfo | documentation)*
5691 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005692 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5693 return (NULL);
5694 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005695 attr = node->properties;
5696 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005697 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005698 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005699 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005700 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005701
5702 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005703 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5704 NULL, NULL, attr);
5705 }
5706 attr = attr->next;
5707 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005708 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005709 /*
5710 * And now for the children...
5711 */
5712 child = node->children;
5713 while (child != NULL) {
5714 if (IS_SCHEMA(child, "appinfo")) {
5715 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005716 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005717 * source = anyURI
5718 * {any attributes with non-schema namespace . . .}>
5719 * Content: ({any})*
5720 */
5721 attr = child->properties;
5722 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005723 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005725 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005726 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005727
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 attr = attr->next;
5733 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005734 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5735 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005736 child = child->next;
5737 } else if (IS_SCHEMA(child, "documentation")) {
5738 /* TODO: make available the content of "documentation". */
5739 /*
5740 * source = anyURI
5741 * {any attributes with non-schema namespace . . .}>
5742 * Content: ({any})*
5743 */
5744 attr = child->properties;
5745 while (attr != NULL) {
5746 if (attr->ns == NULL) {
5747 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005748 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005749 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5750 NULL, NULL, attr);
5751 }
5752 } else {
5753 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5754 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5755 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005756
5757 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005758 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5759 NULL, NULL, attr);
5760 }
5761 }
5762 attr = attr->next;
5763 }
5764 /*
5765 * Attribute "xml:lang".
5766 */
5767 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5768 if (attr != NULL)
5769 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005770 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005771 child = child->next;
5772 } else {
5773 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005774 xmlSchemaPContentErr(ctxt,
5775 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005776 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5777 barked = 1;
5778 child = child->next;
5779 }
5780 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005781
Daniel Veillard4255d502002-04-16 15:50:10 +00005782 return (ret);
5783}
5784
5785/**
5786 * xmlSchemaParseFacet:
5787 * @ctxt: a schema validation context
5788 * @schema: the schema being built
5789 * @node: a subtree containing XML Schema informations
5790 *
5791 * parse a XML schema Facet declaration
5792 * *WARNING* this interface is highly subject to change
5793 *
5794 * Returns the new type structure or NULL in case of error
5795 */
5796static xmlSchemaFacetPtr
5797xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005798 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005799{
5800 xmlSchemaFacetPtr facet;
5801 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005802 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005803
5804 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5805 return (NULL);
5806
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005807 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 if (facet == NULL) {
5809 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5810 return (NULL);
5811 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005812 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005813 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005814 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005815 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5816 "Facet %s has no value\n", node->name, NULL);
5817 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005818 return (NULL);
5819 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005820 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005821 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005822 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005823 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005825 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005826 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005827 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005830 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005831 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005832 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005833 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005834 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005835 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005836 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005837 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005838 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005839 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005840 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005841 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5842 } else if (IS_SCHEMA(node, "minLength")) {
5843 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5844 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005845 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5846 "Unknown facet type %s\n", node->name, NULL);
5847 xmlSchemaFreeFacet(facet);
5848 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005849 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005850 xmlSchemaPValAttrID(ctxt, NULL,
5851 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005852 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005853 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5854 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5855 const xmlChar *fixed;
5856
5857 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5858 if (fixed != NULL) {
5859 if (xmlStrEqual(fixed, BAD_CAST "true"))
5860 facet->fixed = 1;
5861 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005862 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005863 child = node->children;
5864
5865 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005866 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5867 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005868 }
5869 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005870 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5871 "Facet %s has unexpected child content\n",
5872 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005873 }
5874 return (facet);
5875}
5876
5877/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005878 * xmlSchemaParseWildcardNs:
5879 * @ctxt: a schema parser context
5880 * @wildc: the wildcard, already created
5881 * @node: a subtree containing XML Schema informations
5882 *
5883 * Parses the attribute "processContents" and "namespace"
5884 * of a xsd:anyAttribute and xsd:any.
5885 * *WARNING* this interface is highly subject to change
5886 *
5887 * Returns 0 if everything goes fine, a positive error code
5888 * if something is not valid and -1 if an internal error occurs.
5889 */
5890static int
5891xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5892 xmlSchemaPtr schema,
5893 xmlSchemaWildcardPtr wildc,
5894 xmlNodePtr node)
5895{
5896 const xmlChar *pc, *ns, *dictnsItem;
5897 int ret = 0;
5898 xmlChar *nsItem;
5899 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5900 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005901
Daniel Veillardc0826a72004-08-10 14:17:33 +00005902 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5903 if ((pc == NULL)
5904 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5905 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5906 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5907 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5908 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5909 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5910 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005911 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005912 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005913 NULL, node,
5914 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005915 NULL, NULL, NULL);
5916 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005917 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005918 }
5919 /*
5920 * Build the namespace constraints.
5921 */
5922 attr = xmlSchemaGetPropNode(node, "namespace");
5923 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005924 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005925 wildc->any = 1;
5926 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5927 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005928 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005929 return (-1);
5930 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005931 wildc->negNsSet->value = schema->targetNamespace;
5932 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005933 const xmlChar *end, *cur;
5934
5935 cur = ns;
5936 do {
5937 while (IS_BLANK_CH(*cur))
5938 cur++;
5939 end = cur;
5940 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5941 end++;
5942 if (end == cur)
5943 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005944 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005945 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5946 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005947 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005948 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005949 NULL, (xmlNodePtr) attr,
5950 NULL,
5951 "((##any | ##other) | List of (xs:anyURI | "
5952 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005953 nsItem, NULL, NULL, NULL);
5954 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5955 } else {
5956 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5957 dictnsItem = schema->targetNamespace;
5958 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5959 dictnsItem = NULL;
5960 } else {
5961 /*
5962 * Validate the item (anyURI).
5963 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005964 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005965 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5966 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5967 }
5968 /*
5969 * Avoid dublicate namespaces.
5970 */
5971 tmp = wildc->nsSet;
5972 while (tmp != NULL) {
5973 if (dictnsItem == tmp->value)
5974 break;
5975 tmp = tmp->next;
5976 }
5977 if (tmp == NULL) {
5978 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5979 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005980 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005981 return (-1);
5982 }
5983 tmp->value = dictnsItem;
5984 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005985 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005986 wildc->nsSet = tmp;
5987 else
5988 lastNs->next = tmp;
5989 lastNs = tmp;
5990 }
5991
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005992 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005993 xmlFree(nsItem);
5994 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005995 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005996 }
5997 return (ret);
5998}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005999
6000static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006001xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6002 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006003 xmlNodePtr node,
6004 int minOccurs,
6005 int maxOccurs) {
6006
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006007 if ((maxOccurs == 0) && ( minOccurs == 0))
6008 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006009 if (maxOccurs != UNBOUNDED) {
6010 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006011 * TODO: Maybe we should better not create the particle,
6012 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006013 * content model.
6014 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006015 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006016 * 3.9.6 Schema Component Constraint: Particle Correct
6017 *
6018 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006019 if (maxOccurs < 1) {
6020 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006021 * 2.2 {max occurs} must be greater than or equal to 1.
6022 */
6023 xmlSchemaPCustomAttrErr(ctxt,
6024 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006025 NULL, NULL,
6026 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006027 "The value must be greater than or equal to 1");
6028 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6029 } else if (minOccurs > maxOccurs) {
6030 /*
6031 * 2.1 {min occurs} must not be greater than {max occurs}.
6032 */
6033 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006034 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006035 NULL, NULL,
6036 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006037 "The value must not be greater than the value of 'maxOccurs'");
6038 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6039 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006040 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006041 return (0);
6042}
6043
Daniel Veillardc0826a72004-08-10 14:17:33 +00006044/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006045 * xmlSchemaParseAny:
6046 * @ctxt: a schema validation context
6047 * @schema: the schema being built
6048 * @node: a subtree containing XML Schema informations
6049 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006050 * Parsea a XML schema <any> element. A particle and wildcard
6051 * will be created (except if minOccurs==maxOccurs==0, in this case
6052 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006053 * *WARNING* this interface is highly subject to change
6054 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006055 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006056 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006057static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006058xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6059 xmlNodePtr node)
6060{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006061 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006062 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006063 xmlSchemaWildcardPtr wild;
6064 int min, max;
6065 xmlAttrPtr attr;
6066 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006067
6068 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6069 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006070 /*
6071 * Check for illegal attributes.
6072 */
6073 attr = node->properties;
6074 while (attr != NULL) {
6075 if (attr->ns == NULL) {
6076 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6077 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6078 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6079 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6080 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006081 xmlSchemaPIllegalAttrErr(ctxt,
6082 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6083 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006084 }
6085 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006086 xmlSchemaPIllegalAttrErr(ctxt,
6087 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6088 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006089 }
6090 attr = attr->next;
6091 }
6092 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6093 /*
6094 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006095 */
6096 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6097 "(xs:nonNegativeInteger | unbounded)");
6098 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6099 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006100 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6101 /*
6102 * Create & parse the wildcard.
6103 */
6104 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6105 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006106 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006107 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006108 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006109 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006110 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006111 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006112 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006113 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006114 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006115 }
6116 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006117 xmlSchemaPContentErr(ctxt,
6118 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006119 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006120 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006121 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006122 /*
6123 * No component if minOccurs==maxOccurs==0.
6124 */
6125 if ((min == 0) && (max == 0)) {
6126 /* Don't free the wildcard, since it's already on the list. */
6127 return (NULL);
6128 }
6129 /*
6130 * Create the particle.
6131 */
6132 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6133 if (particle == NULL)
6134 return (NULL);
6135 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006136 wild->minOccurs = min;
6137 wild->maxOccurs = max;
6138 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006139
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006140 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006141}
6142
6143/**
6144 * xmlSchemaParseNotation:
6145 * @ctxt: a schema validation context
6146 * @schema: the schema being built
6147 * @node: a subtree containing XML Schema informations
6148 *
6149 * parse a XML schema Notation declaration
6150 *
6151 * Returns the new structure or NULL in case of error
6152 */
6153static xmlSchemaNotationPtr
6154xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006155 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006156{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006157 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006158 xmlSchemaNotationPtr ret;
6159 xmlNodePtr child = NULL;
6160
6161 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6162 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006163 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006164 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006165 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6166 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006167 return (NULL);
6168 }
6169 ret = xmlSchemaAddNotation(ctxt, schema, name);
6170 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 return (NULL);
6172 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006173 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006174
6175 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6176 node, BAD_CAST "id");
6177
6178 if (IS_SCHEMA(child, "annotation")) {
6179 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6180 child = child->next;
6181 }
6182
Daniel Veillard4255d502002-04-16 15:50:10 +00006183 child = node->children;
6184 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006185 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6186 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006187 }
6188 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006189 xmlSchemaPContentErr(ctxt,
6190 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006191 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006192 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006193 }
6194
6195 return (ret);
6196}
6197
6198/**
6199 * xmlSchemaParseAnyAttribute:
6200 * @ctxt: a schema validation context
6201 * @schema: the schema being built
6202 * @node: a subtree containing XML Schema informations
6203 *
6204 * parse a XML schema AnyAttrribute declaration
6205 * *WARNING* this interface is highly subject to change
6206 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006207 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006208 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006209static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006210xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6211 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006212{
Daniel Veillard3646d642004-06-02 19:19:14 +00006213 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006214 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006215 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006216
6217 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6218 return (NULL);
6219
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006220 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6221 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006222 if (ret == NULL) {
6223 return (NULL);
6224 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006225 /*
6226 * Check for illegal attributes.
6227 */
6228 attr = node->properties;
6229 while (attr != NULL) {
6230 if (attr->ns == NULL) {
6231 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6232 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6233 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006234 xmlSchemaPIllegalAttrErr(ctxt,
6235 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6236 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006237 }
6238 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006239 xmlSchemaPIllegalAttrErr(ctxt,
6240 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6241 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006242 }
6243 attr = attr->next;
6244 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006245 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6246 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006247 /*
6248 * Parse the namespace list.
6249 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006250 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006251 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006252 /*
6253 * And now for the children...
6254 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006255 child = node->children;
6256 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006257 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6258 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006259 }
6260 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006261 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006262 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006263 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006264 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006265 }
6266
6267 return (ret);
6268}
6269
6270
6271/**
6272 * xmlSchemaParseAttribute:
6273 * @ctxt: a schema validation context
6274 * @schema: the schema being built
6275 * @node: a subtree containing XML Schema informations
6276 *
6277 * parse a XML schema Attrribute declaration
6278 * *WARNING* this interface is highly subject to change
6279 *
William M. Bracke7091952004-05-11 15:09:58 +00006280 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006281 */
6282static xmlSchemaAttributePtr
6283xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006284 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006285{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006286 const xmlChar *name, *attrValue;
6287 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006288 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006289 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006290 xmlAttrPtr attr, nameAttr;
6291 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006292
6293 /*
6294 * Note that the w3c spec assumes the schema to be validated with schema
6295 * for schemas beforehand.
6296 *
6297 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006298 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006299
6300 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6301 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006302 attr = xmlSchemaGetPropNode(node, "ref");
6303 nameAttr = xmlSchemaGetPropNode(node, "name");
6304
6305 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006306 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006307 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006308 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006309 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006310 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6311 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006312 "One of the attributes 'ref' or 'name' must be present");
6313 return (NULL);
6314 }
6315 if ((topLevel) || (attr == NULL)) {
6316 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006317 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6318 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006319 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006320 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006321 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006322 isRef = 1;
6323
Daniel Veillardc0826a72004-08-10 14:17:33 +00006324 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006325 char buf[50];
6326 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006327
6328 /*
6329 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006330 */
6331 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6332 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6333 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006334 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006335 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006336 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006337 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006338 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006339 if (ret == NULL) {
6340 if (repName != NULL)
6341 xmlFree(repName);
6342 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006343 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006344 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6345 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006346 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006347 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006348 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6349 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006350 /*
6351 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6352 */
6353 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006354 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6355 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006356 "ref", "name");
6357 /*
6358 * Check for illegal attributes.
6359 */
6360 attr = node->properties;
6361 while (attr != NULL) {
6362 if (attr->ns == NULL) {
6363 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6364 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006365 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006366 * 3.2.3 : 3.2
6367 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006368 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006369 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006370 xmlSchemaPIllegalAttrErr(ctxt,
6371 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006372 (xmlSchemaTypePtr) ret, attr);
6373 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6374 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6375 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006376 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6377 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006378 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006379 xmlSchemaPIllegalAttrErr(ctxt,
6380 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6381 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006382 }
6383 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006384 xmlSchemaPIllegalAttrErr(ctxt,
6385 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6386 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006387 }
6388 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006389 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006390 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006391 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006392
Daniel Veillardc0826a72004-08-10 14:17:33 +00006393 /*
6394 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006395 */
6396 if (xmlSchemaPValAttrNode(ctxt,
6397 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006398 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6399 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006400 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006401 /*
6402 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6403 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006404 /*
6405 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6406 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006407 */
6408 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006409 xmlSchemaPSimpleTypeErr(ctxt,
6410 XML_SCHEMAP_NO_XMLNS,
6411 NULL, (xmlNodePtr) nameAttr,
6412 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6413 "The value of type 'xs:NCName' must not match 'xmlns'",
6414 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006415 if (repName != NULL)
6416 xmlFree(repName);
6417 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006418 }
6419 /*
6420 * Evaluate the target namespace
6421 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006422 if (topLevel) {
6423 ns = schema->targetNamespace;
6424 } else {
6425 attr = xmlSchemaGetPropNode(node, "form");
6426 if (attr != NULL) {
6427 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6428 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6429 ns = schema->targetNamespace;
6430 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006431 xmlSchemaPSimpleTypeErr(ctxt,
6432 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6433 NULL, (xmlNodePtr) attr,
6434 NULL, "(qualified | unqualified)",
6435 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006436 }
6437 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006438 ns = schema->targetNamespace;
6439 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006440 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006441 if (ret == NULL) {
6442 if (repName != NULL)
6443 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006444 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006445 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006446 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006447 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006448 if (topLevel)
6449 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006450 /*
6451 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6452 * TODO: Move this to the component layer.
6453 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006454 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006455 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006456 XML_SCHEMAP_NO_XSI,
6457 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006458 "The target namespace must not match '%s'",
6459 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006460 }
6461 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006462 * Check for illegal attributes.
6463 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006464 attr = node->properties;
6465 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006466 if (attr->ns == NULL) {
6467 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6468 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6469 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006470 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6471 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006472 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006473 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6474 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006475 xmlSchemaPIllegalAttrErr(ctxt,
6476 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6477 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006478 }
6479 }
6480 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006481 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6482 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006483 }
6484 attr = attr->next;
6485 }
6486 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006487 node, "type", &ret->typeNs, &ret->typeName);
6488 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006489 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6490 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006491 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006492 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006493 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006494 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6495 if (ret->defValue != NULL)
6496 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006497 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006498 * Attribute "default".
6499 */
6500 attr = xmlSchemaGetPropNode(node, "default");
6501 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006502 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006503 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006504 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006505 */
6506 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6507 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6508 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6509 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006510 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6511 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006512 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006513 /*
6514 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006515 */
6516 attr = xmlSchemaGetPropNode(node, "use");
6517 if (attr != NULL) {
6518 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6519 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6520 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6521 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6522 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6523 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6524 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6525 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006526 xmlSchemaPSimpleTypeErr(ctxt,
6527 XML_SCHEMAP_INVALID_ATTR_USE,
6528 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6529 NULL, "(optional | prohibited | required)",
6530 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006531 } else
6532 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006533 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006534 * 3.2.3 : 2
6535 * If default and use are both present, use must have
6536 * the actual value optional.
6537 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006538 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6539 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006540 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006541 xmlSchemaPSimpleTypeErr(ctxt,
6542 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6543 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6544 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006545 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 /*
6550 * And now for the children...
6551 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006552 child = node->children;
6553 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006554 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6555 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006556 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006558 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006560 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006561 * 3.2.3 : 3.2
6562 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006563 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006564 */
6565 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6566 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6567 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006568 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006569 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6570 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006571 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006572 }
6573 } else {
6574 if (IS_SCHEMA(child, "simpleType")) {
6575 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006576 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006577 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006578 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006579 */
6580 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6581 &repName, (xmlSchemaTypePtr) ret, node, child,
6582 "The attribute 'type' and the <simpleType> child "
6583 "are mutually exclusive", NULL);
6584 } else
6585 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6586 child = child->next;
6587 }
6588 if (child != NULL)
6589 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6590 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6591 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006592 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006593 /*
6594 * Cleanup.
6595 */
6596 if (repName != NULL)
6597 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006598 return (ret);
6599}
6600
6601/**
6602 * xmlSchemaParseAttributeGroup:
6603 * @ctxt: a schema validation context
6604 * @schema: the schema being built
6605 * @node: a subtree containing XML Schema informations
6606 *
6607 * parse a XML schema Attribute Group declaration
6608 * *WARNING* this interface is highly subject to change
6609 *
6610 * Returns the attribute group or NULL in case of error.
6611 */
6612static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006613xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006614 xmlSchemaPtr schema, xmlNodePtr node,
6615 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006616{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006617 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006618 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006619 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006620 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006621 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006622
6623 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6624 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006625
6626 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006627 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006628 if ((topLevel) || (attr == NULL)) {
6629 /*
6630 * Parse as an attribute group definition.
6631 * Note that those are allowed at top level only.
6632 */
6633 if (nameAttr == NULL) {
6634 xmlSchemaPMissingAttrErr(ctxt,
6635 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006636 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006637 return (NULL);
6638 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006639 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006640 * (xmlNodePtr) nameAttr);
6641 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006642 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006643 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006644 */
6645 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006646 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006647 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6648 return (NULL);
6649 }
6650 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6651 if (ret == NULL)
6652 return (NULL);
6653 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6654 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6655 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006656 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006657 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006658 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006659 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006660
6661 /*
6662 * Parse as an attribute group definition reference.
6663 */
6664 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006665 xmlSchemaPMissingAttrErr(ctxt,
6666 XML_SCHEMAP_S4S_ATTR_MISSING,
6667 NULL, node, "ref", NULL);
6668 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006669 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006670 NULL, NULL, attr, &refNs,&ref);
6671
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006672 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006673 name = (const xmlChar *) buf;
6674 if (name == NULL) {
6675 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6676 "attribute group definition reference", node);
6677 return (NULL);
6678 }
6679 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6680 if (ret == NULL)
6681 return (NULL);
6682 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6683 ret->ref = ref;
6684 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006685 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006686 xmlSchemaCheckReference(ctxt, schema, node,
6687 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006688 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006689 /*
6690 * Check for illegal attributes.
6691 */
6692 attr = node->properties;
6693 while (attr != NULL) {
6694 if (attr->ns == NULL) {
6695 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6696 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006697 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006698 {
6699 xmlSchemaPIllegalAttrErr(ctxt,
6700 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6701 NULL, NULL, attr);
6702 }
6703 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6704 xmlSchemaPIllegalAttrErr(ctxt,
6705 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6706 NULL, NULL, attr);
6707 }
6708 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006709 }
6710 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006711 /*
6712 * And now for the children...
6713 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006714 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006715 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006716 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006717 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006718 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6719 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006720 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006721 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006722 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006723 if (IS_SCHEMA(child, "anyAttribute")) {
6724 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6725 child = child->next;
6726 }
6727 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006728 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006729 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006730 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6731 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006732 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006733 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006734 ctxt->container = oldcontainer;
6735 return (ret);
6736}
6737
6738/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006739 * xmlSchemaPValAttrFormDefault:
6740 * @value: the value
6741 * @flags: the flags to be modified
6742 * @flagQualified: the specific flag for "qualified"
6743 *
6744 * Returns 0 if the value is valid, 1 otherwise.
6745 */
6746static int
6747xmlSchemaPValAttrFormDefault(const xmlChar *value,
6748 int *flags,
6749 int flagQualified)
6750{
6751 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6752 if ((*flags & flagQualified) == 0)
6753 *flags |= flagQualified;
6754 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006755 return (1);
6756
William M. Brack2f2a6632004-08-20 23:09:47 +00006757 return (0);
6758}
6759
6760/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006761 * xmlSchemaPValAttrBlockFinal:
6762 * @value: the value
6763 * @flags: the flags to be modified
6764 * @flagAll: the specific flag for "#all"
6765 * @flagExtension: the specific flag for "extension"
6766 * @flagRestriction: the specific flag for "restriction"
6767 * @flagSubstitution: the specific flag for "substitution"
6768 * @flagList: the specific flag for "list"
6769 * @flagUnion: the specific flag for "union"
6770 *
6771 * Validates the value of the attribute "final" and "block". The value
6772 * is converted into the specified flag values and returned in @flags.
6773 *
6774 * Returns 0 if the value is valid, 1 otherwise.
6775 */
6776
6777static int
6778xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006779 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006780 int flagAll,
6781 int flagExtension,
6782 int flagRestriction,
6783 int flagSubstitution,
6784 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006785 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006786{
6787 int ret = 0;
6788
6789 /*
6790 * TODO: This does not check for dublicate entries.
6791 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006792 if ((flags == NULL) || (value == NULL))
6793 return (-1);
6794 if (value[0] == 0)
6795 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006796 if (xmlStrEqual(value, BAD_CAST "#all")) {
6797 if (flagAll != -1)
6798 *flags |= flagAll;
6799 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006800 if (flagExtension != -1)
6801 *flags |= flagExtension;
6802 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006803 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006804 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006805 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006806 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006807 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006808 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006809 *flags |= flagUnion;
6810 }
6811 } else {
6812 const xmlChar *end, *cur = value;
6813 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006814
Daniel Veillardc0826a72004-08-10 14:17:33 +00006815 do {
6816 while (IS_BLANK_CH(*cur))
6817 cur++;
6818 end = cur;
6819 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6820 end++;
6821 if (end == cur)
6822 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006823 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006824 if (xmlStrEqual(item, BAD_CAST "extension")) {
6825 if (flagExtension != -1) {
6826 if ((*flags & flagExtension) == 0)
6827 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006828 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006829 ret = 1;
6830 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6831 if (flagRestriction != -1) {
6832 if ((*flags & flagRestriction) == 0)
6833 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006834 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006835 ret = 1;
6836 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6837 if (flagSubstitution != -1) {
6838 if ((*flags & flagSubstitution) == 0)
6839 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006840 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006841 ret = 1;
6842 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6843 if (flagList != -1) {
6844 if ((*flags & flagList) == 0)
6845 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006846 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006847 ret = 1;
6848 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6849 if (flagUnion != -1) {
6850 if ((*flags & flagUnion) == 0)
6851 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006852 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006853 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006854 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006855 ret = 1;
6856 if (item != NULL)
6857 xmlFree(item);
6858 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006859 } while ((ret == 0) && (*cur != 0));
6860 }
6861
Daniel Veillardc0826a72004-08-10 14:17:33 +00006862 return (ret);
6863}
6864
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006865static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006866xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006867 xmlSchemaIDCPtr idc,
6868 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006869 xmlAttrPtr attr,
6870 int isField)
6871{
6872 xmlNodePtr node;
6873
6874 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006875 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006876 * Schema Component Constraint: Selector Value OK
6877 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006878 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006879 * in [XPath].
6880 */
6881 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006882 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006883 XML_SCHEMAP_INTERNAL,
6884 "Internal error: xmlSchemaCheckCSelectorXPath, "
6885 "the selector is not specified.\n", NULL, NULL);
6886 return (-1);
6887 }
6888 if (attr == NULL)
6889 node = idc->node;
6890 else
6891 node = (xmlNodePtr) attr;
6892 if (selector->xpath == NULL) {
6893 xmlSchemaPCustomErr(ctxt,
6894 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006895 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6896 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006897 "The XPath expression of the selector is not valid", NULL);
6898 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6899 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006900 const xmlChar **nsArray = NULL;
6901 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006902 /*
6903 * Compile the XPath expression.
6904 */
6905 /*
6906 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006907 * TODO: Call xmlPatterncompile with different options for selector/
6908 * field.
6909 */
6910 nsList = xmlGetNsList(attr->doc, attr->parent);
6911 /*
6912 * Build an array of prefixes and namespaces.
6913 */
6914 if (nsList != NULL) {
6915 int i, count = 0;
6916 xmlNsPtr ns;
6917
6918 for (i = 0; nsList[i] != NULL; i++)
6919 count++;
6920
6921 nsArray = (const xmlChar **) xmlMalloc(
6922 (count * 2 + 1) * sizeof(const xmlChar *));
6923 if (nsArray == NULL) {
6924 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6925 NULL);
6926 return (-1);
6927 }
6928 for (i = 0; i < count; i++) {
6929 ns = nsList[i];
6930 nsArray[2 * i] = nsList[i]->href;
6931 nsArray[2 * i + 1] = nsList[i]->prefix;
6932 }
6933 nsArray[count * 2] = NULL;
6934 xmlFree(nsList);
6935 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006936 /*
6937 * TODO: Differentiate between "selector" and "field".
6938 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006939 if (isField)
6940 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006941 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006942 else
6943 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006944 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006945 if (nsArray != NULL)
6946 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006947
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006948 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006949 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006950 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006951 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6952 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006953 "The XPath expression '%s' could not be "
6954 "compiled", selector->xpath);
6955 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006956 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006957 }
6958 return (0);
6959}
6960
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006961#define ADD_ANNOTATION(annot) \
6962 xmlSchemaAnnotPtr cur = item->annot; \
6963 if (item->annot == NULL) { \
6964 item->annot = annot; \
6965 return (annot); \
6966 } \
6967 cur = item->annot; \
6968 if (cur->next != NULL) { \
6969 cur = cur->next; \
6970 } \
6971 cur->next = annot;
6972
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006973/**
6974 * xmlSchemaAssignAnnotation:
6975 * @item: the schema component
6976 * @annot: the annotation
6977 *
6978 * Adds the annotation to the given schema component.
6979 *
6980 * Returns the given annotaion.
6981 */
6982static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006983xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6984 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006985{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006986 if ((annItem == NULL) || (annot == NULL))
6987 return (NULL);
6988 switch (annItem->type) {
6989 case XML_SCHEMA_TYPE_ELEMENT: {
6990 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6991 ADD_ANNOTATION(annot)
6992 }
6993 break;
6994 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6995 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6996 ADD_ANNOTATION(annot)
6997 }
6998 break;
6999 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
7000 case XML_SCHEMA_TYPE_ANY: {
7001 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7002 ADD_ANNOTATION(annot)
7003 }
7004 break;
7005 case XML_SCHEMA_TYPE_PARTICLE:
7006 case XML_SCHEMA_TYPE_IDC_KEY:
7007 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007008 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007009 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7010 ADD_ANNOTATION(annot)
7011 }
7012 break;
7013 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7014 xmlSchemaAttributeGroupPtr item =
7015 (xmlSchemaAttributeGroupPtr) annItem;
7016 ADD_ANNOTATION(annot)
7017 }
7018 break;
7019 case XML_SCHEMA_TYPE_NOTATION: {
7020 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7021 ADD_ANNOTATION(annot)
7022 }
7023 break;
7024 case XML_SCHEMA_FACET_MININCLUSIVE:
7025 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7026 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7027 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7028 case XML_SCHEMA_FACET_TOTALDIGITS:
7029 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7030 case XML_SCHEMA_FACET_PATTERN:
7031 case XML_SCHEMA_FACET_ENUMERATION:
7032 case XML_SCHEMA_FACET_WHITESPACE:
7033 case XML_SCHEMA_FACET_LENGTH:
7034 case XML_SCHEMA_FACET_MAXLENGTH:
7035 case XML_SCHEMA_FACET_MINLENGTH: {
7036 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7037 ADD_ANNOTATION(annot)
7038 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007039 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007040 case XML_SCHEMA_TYPE_SIMPLE:
7041 case XML_SCHEMA_TYPE_COMPLEX: {
7042 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7043 ADD_ANNOTATION(annot)
7044 }
7045 break;
7046 case XML_SCHEMA_TYPE_GROUP: {
7047 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7048 ADD_ANNOTATION(annot)
7049 }
7050 break;
7051 case XML_SCHEMA_TYPE_SEQUENCE:
7052 case XML_SCHEMA_TYPE_CHOICE:
7053 case XML_SCHEMA_TYPE_ALL: {
7054 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7055 ADD_ANNOTATION(annot)
7056 }
7057 break;
7058 default:
7059 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007060 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007061 NULL, NULL, NULL,
7062 "Internal error: xmlSchemaAddAnnotation, "
7063 "The item is not a annotated schema component", NULL);
7064 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007065 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007066 return (annot);
7067}
7068
7069/**
7070 * xmlSchemaParseIDCSelectorAndField:
7071 * @ctxt: a schema validation context
7072 * @schema: the schema being built
7073 * @node: a subtree containing XML Schema informations
7074 *
7075 * Parses a XML Schema identity-contraint definition's
7076 * <selector> and <field> elements.
7077 *
7078 * Returns the parsed identity-constraint definition.
7079 */
7080static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007081xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007082 xmlSchemaPtr schema,
7083 xmlSchemaIDCPtr idc,
7084 xmlNodePtr node,
7085 int isField)
7086{
7087 xmlSchemaIDCSelectPtr item;
7088 xmlNodePtr child = NULL;
7089 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007090
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007091 /*
7092 * Check for illegal attributes.
7093 */
7094 attr = node->properties;
7095 while (attr != NULL) {
7096 if (attr->ns == NULL) {
7097 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7098 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007099 xmlSchemaPIllegalAttrErr(ctxt,
7100 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7101 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007102 }
7103 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007104 xmlSchemaPIllegalAttrErr(ctxt,
7105 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7106 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007107 }
7108 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007109 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007110 /*
7111 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007112 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007113 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7114 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007115 xmlSchemaPErrMemory(ctxt,
7116 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007117 NULL);
7118 return (NULL);
7119 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007120 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007121 /*
7122 * Attribute "xpath" (mandatory).
7123 */
7124 attr = xmlSchemaGetPropNode(node, "xpath");
7125 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007126 xmlSchemaPMissingAttrErr(ctxt,
7127 XML_SCHEMAP_S4S_ATTR_MISSING,
7128 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007129 "name", NULL);
7130 } else {
7131 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7132 /*
7133 * URGENT TODO: "field"s have an other syntax than "selector"s.
7134 */
7135
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007136 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7137 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007138 xmlSchemaPErr(ctxt,
7139 (xmlNodePtr) attr,
7140 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007141 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007142 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007143 NULL, NULL);
7144 }
7145
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007146 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007147 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007148 /*
7149 * And now for the children...
7150 */
7151 child = node->children;
7152 if (IS_SCHEMA(child, "annotation")) {
7153 /*
7154 * Add the annotation to the parent IDC.
7155 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007156 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007157 xmlSchemaParseAnnotation(ctxt, schema, child));
7158 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007159 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007160 if (child != NULL) {
7161 xmlSchemaPContentErr(ctxt,
7162 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007163 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007164 NULL, "(annotation?)");
7165 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007166
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007167 return (item);
7168}
7169
7170/**
7171 * xmlSchemaParseIDC:
7172 * @ctxt: a schema validation context
7173 * @schema: the schema being built
7174 * @node: a subtree containing XML Schema informations
7175 *
7176 * Parses a XML Schema identity-contraint definition.
7177 *
7178 * Returns the parsed identity-constraint definition.
7179 */
7180static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007181xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007182 xmlSchemaPtr schema,
7183 xmlNodePtr node,
7184 xmlSchemaTypeType idcCategory,
7185 const xmlChar *targetNamespace)
7186{
7187 xmlSchemaIDCPtr item = NULL;
7188 xmlNodePtr child = NULL;
7189 xmlAttrPtr attr;
7190 const xmlChar *name = NULL;
7191 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7192 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007193
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007194 /*
7195 * Check for illegal attributes.
7196 */
7197 attr = node->properties;
7198 while (attr != NULL) {
7199 if (attr->ns == NULL) {
7200 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7201 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7202 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7203 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007204 xmlSchemaPIllegalAttrErr(ctxt,
7205 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7206 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007207 }
7208 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007209 xmlSchemaPIllegalAttrErr(ctxt,
7210 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7211 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007212 }
7213 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007214 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007215 /*
7216 * Attribute "name" (mandatory).
7217 */
7218 attr = xmlSchemaGetPropNode(node, "name");
7219 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007220 xmlSchemaPMissingAttrErr(ctxt,
7221 XML_SCHEMAP_S4S_ATTR_MISSING,
7222 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007223 "name", NULL);
7224 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007225 } else if (xmlSchemaPValAttrNode(ctxt,
7226 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007227 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7228 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007229 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007230 /*
7231 * Create the component.
7232 */
7233 if (schema->idcDef == NULL)
7234 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007235 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007236 return (NULL);
7237
7238 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7239 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007240 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007241 "allocating an identity-constraint definition", NULL);
7242 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007243 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007244 /*
7245 * Add the IDC to the list of IDCs on the schema component.
7246 */
7247 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007248 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007249 xmlSchemaPCustomErrExt(ctxt,
7250 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007251 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007252 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007253 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007254 name, targetNamespace, NULL);
7255 xmlFree(item);
7256 return (NULL);
7257 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007258 memset(item, 0, sizeof(xmlSchemaIDC));
7259 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007260 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007261 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007262 if (ctxt->assemble != NULL)
7263 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007264 /*
7265 * The target namespace of the parent element declaration.
7266 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007267 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007268 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7269 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007270 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7271 /*
7272 * Attribute "refer" (mandatory).
7273 */
7274 attr = xmlSchemaGetPropNode(node, "refer");
7275 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007276 xmlSchemaPMissingAttrErr(ctxt,
7277 XML_SCHEMAP_S4S_ATTR_MISSING,
7278 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007279 "refer", NULL);
7280 } else {
7281 /*
7282 * Create a reference item.
7283 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007284 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007285 NULL, NULL);
7286 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007287 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007288 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007289 NULL, NULL, attr,
7290 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007291 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007292 xmlSchemaCheckReference(ctxt, schema, node,
7293 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007294 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007295 }
7296 }
7297 /*
7298 * And now for the children...
7299 */
7300 child = node->children;
7301 if (IS_SCHEMA(child, "annotation")) {
7302 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7303 child = child->next;
7304 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007305 if (child == NULL) {
7306 xmlSchemaPContentErr(ctxt,
7307 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007308 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007309 "A child element is missing",
7310 "(annotation?, (selector, field+))");
7311 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007312 /*
7313 * Child element <selector>.
7314 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007315 if (IS_SCHEMA(child, "selector")) {
7316 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007317 item, child, 0);
7318 child = child->next;
7319 /*
7320 * Child elements <field>.
7321 */
7322 if (IS_SCHEMA(child, "field")) {
7323 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007324 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007325 item, child, 1);
7326 if (field != NULL) {
7327 field->index = item->nbFields;
7328 item->nbFields++;
7329 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007330 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007331 else
7332 item->fields = field;
7333 lastField = field;
7334 }
7335 child = child->next;
7336 } while (IS_SCHEMA(child, "field"));
7337 } else {
7338 xmlSchemaPContentErr(ctxt,
7339 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007340 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007341 NULL, "(annotation?, (selector, field+))");
7342 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007343 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007344 if (child != NULL) {
7345 xmlSchemaPContentErr(ctxt,
7346 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007347 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007348 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007349 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007350
7351 return (item);
7352}
7353
Daniel Veillardc0826a72004-08-10 14:17:33 +00007354/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007355 * xmlSchemaParseElement:
7356 * @ctxt: a schema validation context
7357 * @schema: the schema being built
7358 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007359 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007360 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007361 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007362 * *WARNING* this interface is highly subject to change
7363 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007364 * Returns the element declaration or a particle; NULL in case
7365 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007366 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007367static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007368xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007369 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007370{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007371 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007372 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007373 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007374 xmlNodePtr child = NULL;
7375 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007376 int min, max, isRef = 0;
7377 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007378
7379 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7380 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007381
Daniel Veillard4255d502002-04-16 15:50:10 +00007382 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007383 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007384 /*
7385 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007386 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007387 * robust.
7388 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007389 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007390 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007391 if ((topLevel) || (attr == NULL)) {
7392 if (nameAttr == NULL) {
7393 xmlSchemaPMissingAttrErr(ctxt,
7394 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007395 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007396 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007397 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007398 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007399 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007400
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007401 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007402 child = node->children;
7403 if (IS_SCHEMA(child, "annotation")) {
7404 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7405 child = child->next;
7406 }
7407 /*
7408 * Skip particle part if a global declaration.
7409 */
7410 if (topLevel)
7411 goto declaration_part;
7412 /*
7413 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007414 */
7415 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7416 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7417 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007418 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7419 if (particle == NULL)
7420 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007421
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007422 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7423
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007424 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007425 const xmlChar *refNs = NULL, *ref = NULL;
7426 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007427 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007428 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007429 */
7430 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007431 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007432 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007433 /*
7434 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007435 */
7436 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007437 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007438 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007439 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007440 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007441 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007442 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007443 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007444 attr = node->properties;
7445 while (attr != NULL) {
7446 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007447 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7448 xmlStrEqual(attr->name, BAD_CAST "name") ||
7449 xmlStrEqual(attr->name, BAD_CAST "id") ||
7450 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7451 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7452 {
7453 attr = attr->next;
7454 continue;
7455 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007456 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007457 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007458 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007459 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007460 "Only the attributes 'minOccurs', 'maxOccurs' and "
7461 "'id' are allowed in addition to 'ref'");
7462 break;
7463 }
7464 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7465 xmlSchemaPIllegalAttrErr(ctxt,
7466 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007467 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007468 }
7469 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007470 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007471 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007472 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007473 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007474 if (child != NULL) {
7475 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7476 NULL, NULL, node, child, NULL, "(annotation?)");
7477 }
7478 if ((min == 0) && (max == 0))
7479 goto return_null;
7480 /*
7481 * Create the reference item.
7482 */
7483 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7484 ref, refNs);
7485 if (refer == NULL)
7486 goto return_null;
7487 particle->children = (xmlSchemaTreeItemPtr) refer;
7488 particle->annot = annot;
7489 /*
7490 * Add to assembled items; the reference need to be resolved.
7491 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007492 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007493 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7494
7495 return ((xmlSchemaBasicItemPtr) particle);
7496 }
7497 /*
7498 * The declaration part ===============================================
7499 */
7500declaration_part:
7501 {
7502 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7503 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7504
7505 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007506 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007507 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007508 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007509 * Evaluate the target namespace.
7510 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007511 if (topLevel) {
7512 ns = schema->targetNamespace;
7513 } else {
7514 attr = xmlSchemaGetPropNode(node, "form");
7515 if (attr != NULL) {
7516 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7517 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007518 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007519 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007520 xmlSchemaPSimpleTypeErr(ctxt,
7521 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7522 NULL, (xmlNodePtr) attr,
7523 NULL, "(qualified | unqualified)",
7524 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007525 }
7526 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007527 ns = schema->targetNamespace;
7528 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007529 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007530 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007531 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007532 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007533 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7534 decl->node = node;
7535 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007536 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007537 * Check for illegal attributes.
7538 */
William M. Bracke7091952004-05-11 15:09:58 +00007539 attr = node->properties;
7540 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007541 if (attr->ns == NULL) {
7542 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7543 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007544 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007545 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007546 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007547 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007548 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7549 {
7550 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007551 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007552 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007553 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007554 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007555 xmlSchemaPIllegalAttrErr(ctxt,
7556 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7557 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007558 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007559 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7560 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007561 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7562
7563 xmlSchemaPIllegalAttrErr(ctxt,
7564 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007565 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007566 }
7567 }
7568 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007569
Daniel Veillardc0826a72004-08-10 14:17:33 +00007570 xmlSchemaPIllegalAttrErr(ctxt,
7571 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007572 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007573 }
7574 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007575 }
William M. Bracke7091952004-05-11 15:09:58 +00007576 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007577 * Extract/validate attributes.
7578 */
7579 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007580 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007581 * Process top attributes of global element declarations here.
7582 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007583 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7584 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007585 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7586 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7587 &(decl->substGroupNs), &(decl->substGroup));
7588 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007589 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007590 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007591 /*
7592 * Attribute "final".
7593 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007594 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007595 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007596 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7597 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7598 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7599 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007600 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007601 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7602 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007603 -1,
7604 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7605 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007606 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007607 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007608 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7609 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007610 attrValue, NULL, NULL, NULL);
7611 }
7612 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007613 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007614 /*
7615 * Attribute "block".
7616 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007617 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007618 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007619 /*
7620 * Apply default "block" values.
7621 */
7622 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7623 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7624 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7625 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7626 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7627 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007628 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007629 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7630 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007631 -1,
7632 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007633 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007634 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7635 xmlSchemaPSimpleTypeErr(ctxt,
7636 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007637 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007638 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007639 "restriction | substitution))", attrValue,
7640 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007641 }
7642 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007643 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007644 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007645 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007646
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007647 attr = xmlSchemaGetPropNode(node, "type");
7648 if (attr != NULL) {
7649 xmlSchemaPValAttrNodeQName(ctxt, schema,
7650 NULL, (xmlSchemaTypePtr) decl, attr,
7651 &(decl->namedTypeNs), &(decl->namedType));
7652 xmlSchemaCheckReference(ctxt, schema, node,
7653 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7654 }
7655 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7656 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007657 if (attr != NULL) {
7658 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007659 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007660 /*
7661 * 3.3.3 : 1
7662 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007663 */
7664 xmlSchemaPMutualExclAttrErr(ctxt,
7665 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007666 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007667 "default", "fixed");
7668 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007669 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7670 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007671 }
William M. Bracke7091952004-05-11 15:09:58 +00007672 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007673 /*
7674 * And now for the children...
7675 */
7676 oldcontainer = ctxt->container;
7677 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007678 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007679 /*
7680 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007681 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007682 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007683 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007684 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007685 xmlSchemaPContentErr(ctxt,
7686 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007687 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007689 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007690 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007691 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007692 child = child->next;
7693 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007694 /*
7695 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007696 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007697 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007698 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007699 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007700 xmlSchemaPContentErr(ctxt,
7701 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007702 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007703 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007704 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007705 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007706 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007707 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007708 }
William M. Bracke7091952004-05-11 15:09:58 +00007709 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007710 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007711 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007712 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007713 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007714 } else if (IS_SCHEMA(child, "key")) {
7715 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007716 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007717 } else if (IS_SCHEMA(child, "keyref")) {
7718 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007719 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007720 }
7721 if (lastIDC != NULL)
7722 lastIDC->next = curIDC;
7723 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007724 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007725 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007726 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007727 }
7728 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007729 xmlSchemaPContentErr(ctxt,
7730 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007731 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007732 NULL, "(annotation?, ((simpleType | complexType)?, "
7733 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007734 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007735 ctxt->container = oldcontainer;
7736 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007737 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007738 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007739 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007740 * different layer.
7741 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007742 FREE_AND_NULL(des)
7743 if (topLevel)
7744 return ((xmlSchemaBasicItemPtr) decl);
7745 else {
7746 particle->children = (xmlSchemaTreeItemPtr) decl;
7747 return ((xmlSchemaBasicItemPtr) particle);
7748 }
7749
7750return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007751 FREE_AND_NULL(des);
7752 if (annot != NULL) {
7753 if (particle != NULL)
7754 particle->annot = NULL;
7755 if (decl != NULL)
7756 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007757 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007758 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007759 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007760}
7761
7762/**
7763 * xmlSchemaParseUnion:
7764 * @ctxt: a schema validation context
7765 * @schema: the schema being built
7766 * @node: a subtree containing XML Schema informations
7767 *
7768 * parse a XML schema Union definition
7769 * *WARNING* this interface is highly subject to change
7770 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007771 * Returns -1 in case of internal error, 0 in case of success and a positive
7772 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007773 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007774static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007775xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007776 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007777{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007778 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007779 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007780 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007781 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007782
7783 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007784 return (-1);
7785 /* Not a component, don't create it. */
7786 type = ctxt->ctxtType;
7787 /*
7788 * Mark the simple type as being of variety "union".
7789 */
7790 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007791 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007792 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7793 * then the ·simple ur-type definition·."
7794 */
7795 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007796 /*
7797 * Check for illegal attributes.
7798 */
7799 attr = node->properties;
7800 while (attr != NULL) {
7801 if (attr->ns == NULL) {
7802 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7803 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007804 xmlSchemaPIllegalAttrErr(ctxt,
7805 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7806 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007807 }
7808 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007809 xmlSchemaPIllegalAttrErr(ctxt,
7810 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7811 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007812 }
7813 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007814 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007815 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007816 /*
7817 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007818 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007819 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007820 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007821 if (attr != NULL) {
7822 const xmlChar *end;
7823 xmlChar *tmp;
7824 const xmlChar *localName, *nsName;
7825 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7826 xmlSchemaQNameRefPtr ref;
7827
7828 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007829 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007830 do {
7831 while (IS_BLANK_CH(*cur))
7832 cur++;
7833 end = cur;
7834 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7835 end++;
7836 if (end == cur)
7837 break;
7838 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007839 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7840 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007841 /*
7842 * Create the member type link.
7843 */
7844 link = (xmlSchemaTypeLinkPtr)
7845 xmlMalloc(sizeof(xmlSchemaTypeLink));
7846 if (link == NULL) {
7847 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7848 "allocating a type link", NULL);
7849 return (-1);
7850 }
7851 link->type = NULL;
7852 link->next = NULL;
7853 if (lastLink == NULL)
7854 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007855 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007856 lastLink->next = link;
7857 lastLink = link;
7858 /*
7859 * Create a reference item.
7860 */
7861 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7862 localName, nsName);
7863 if (ref == NULL) {
7864 FREE_AND_NULL(tmp)
7865 return (-1);
7866 }
7867 /*
7868 * Assign the reference to the link, it will be resolved
7869 * later during fixup of the union simple type.
7870 */
7871 link->type = (xmlSchemaTypePtr) ref;
7872 }
7873 FREE_AND_NULL(tmp)
7874 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007875 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007876
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007877 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007878 /*
7879 * And now for the children...
7880 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007881 child = node->children;
7882 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007883 /*
7884 * Add the annotation to the simple type ancestor.
7885 */
7886 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7887 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007888 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007889 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007890 if (IS_SCHEMA(child, "simpleType")) {
7891 xmlSchemaTypePtr subtype, last = NULL;
7892
7893 /*
7894 * Anchor the member types in the "subtypes" field of the
7895 * simple type.
7896 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007897 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007898 subtype = (xmlSchemaTypePtr)
7899 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7900 if (subtype != NULL) {
7901 if (last == NULL) {
7902 type->subtypes = subtype;
7903 last = subtype;
7904 } else {
7905 last->next = subtype;
7906 last = subtype;
7907 }
7908 last->next = NULL;
7909 }
7910 child = child->next;
7911 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007912 }
7913 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007914 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007915 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007916 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007917 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007918 if ((attr == NULL) && (type->subtypes == NULL)) {
7919 /*
7920 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007921 * Either the memberTypes [attribute] of the <union> element must
7922 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007923 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007924 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007925 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7926 NULL, NULL, node,
7927 "Either the attribute 'memberTypes' or "
7928 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007929 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007930 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007931}
7932
7933/**
7934 * xmlSchemaParseList:
7935 * @ctxt: a schema validation context
7936 * @schema: the schema being built
7937 * @node: a subtree containing XML Schema informations
7938 *
7939 * parse a XML schema List definition
7940 * *WARNING* this interface is highly subject to change
7941 *
William M. Bracke7091952004-05-11 15:09:58 +00007942 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007943 * 1 in case of success.
7944 */
7945static xmlSchemaTypePtr
7946xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007947 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007948{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007949 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007950 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007951 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007952
7953 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7954 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007955 /* Not a component, don't create it. */
7956 type = ctxt->ctxtType;
7957 /*
7958 * Mark the type as being of variety "list".
7959 */
7960 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007961 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007962 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7963 * then the ·simple ur-type definition·."
7964 */
7965 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007966 /*
7967 * Check for illegal attributes.
7968 */
7969 attr = node->properties;
7970 while (attr != NULL) {
7971 if (attr->ns == NULL) {
7972 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7973 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007974 xmlSchemaPIllegalAttrErr(ctxt,
7975 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7976 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007977 }
7978 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007979 xmlSchemaPIllegalAttrErr(ctxt,
7980 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7981 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007982 }
7983 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007984 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007985
7986 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7987
William M. Brack2f2a6632004-08-20 23:09:47 +00007988 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007989 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7990 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007991 */
7992 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007993 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007994 /*
7995 * And now for the children...
7996 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007997 child = node->children;
7998 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007999 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8000 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008001 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008002 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008003 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008004 /*
8005 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008006 * Either the itemType [attribute] or the <simpleType> [child] of
8007 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008008 */
8009 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008010 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008011 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008012 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008013 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008014 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008015 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008016 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008017 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008018 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008019 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008020 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008021 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008022 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008023 "Either the attribute 'itemType' or the <simpleType> child "
8024 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008025 }
8026 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008027 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008028 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008029 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008030 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008031 if ((type->ref == NULL) &&
8032 (type->subtypes == NULL) &&
8033 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008034 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008035 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008036 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008037 "Either the attribute 'itemType' or the <simpleType> child "
8038 "must be present", NULL);
8039 }
8040 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008041}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008042
Daniel Veillard4255d502002-04-16 15:50:10 +00008043/**
8044 * xmlSchemaParseSimpleType:
8045 * @ctxt: a schema validation context
8046 * @schema: the schema being built
8047 * @node: a subtree containing XML Schema informations
8048 *
8049 * parse a XML schema Simple Type definition
8050 * *WARNING* this interface is highly subject to change
8051 *
William M. Bracke7091952004-05-11 15:09:58 +00008052 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008053 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008054 */
8055static xmlSchemaTypePtr
8056xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008057 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008058{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008059 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008060 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008061 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008062 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008063
8064 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8065 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008066
Daniel Veillardc0826a72004-08-10 14:17:33 +00008067 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008068 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008069 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008070 xmlSchemaPMissingAttrErr(ctxt,
8071 XML_SCHEMAP_S4S_ATTR_MISSING,
8072 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008073 "name", NULL);
8074 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008075 } else {
8076 if (xmlSchemaPValAttrNode(ctxt,
8077 NULL, NULL, attr,
8078 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8079 return (NULL);
8080 /*
8081 * Skip built-in types.
8082 */
8083 if (ctxt->isS4S) {
8084 xmlSchemaTypePtr biType;
8085
8086 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8087 if (biType != NULL)
8088 return (biType);
8089 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008090 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008091 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008092
Daniel Veillardc0826a72004-08-10 14:17:33 +00008093 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008094 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008095
Daniel Veillard01fa6152004-06-29 17:04:39 +00008096 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008097 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008098 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008099 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008100 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008101 if (type == NULL)
8102 return (NULL);
8103 type->node = node;
8104 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008105 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008106 /*
8107 * Check for illegal attributes.
8108 */
8109 attr = node->properties;
8110 while (attr != NULL) {
8111 if (attr->ns == NULL) {
8112 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008113 xmlSchemaPIllegalAttrErr(ctxt,
8114 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8115 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008116 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008117 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008118 xmlSchemaPIllegalAttrErr(ctxt,
8119 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8120 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008121 }
8122 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008123 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008124 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008125 /*
8126 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008127 *
8128 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008129 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008130 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008131 if (type == NULL)
8132 return (NULL);
8133 type->node = node;
8134 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008135 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008136 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8137 /*
8138 * Check for illegal attributes.
8139 */
8140 attr = node->properties;
8141 while (attr != NULL) {
8142 if (attr->ns == NULL) {
8143 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8144 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008145 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008146 xmlSchemaPIllegalAttrErr(ctxt,
8147 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8148 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008149 }
8150 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008151 xmlSchemaPIllegalAttrErr(ctxt,
8152 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8153 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008154 }
8155 attr = attr->next;
8156 }
8157 /*
8158 * Attribute "final".
8159 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008160 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008161 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008162 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8163 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8164 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8165 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8166 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8167 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008168 } else {
8169 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008170 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8171 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008172 XML_SCHEMAS_TYPE_FINAL_LIST,
8173 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008175 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008176 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008177 type, (xmlNodePtr) attr,
8178 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008179 attrValue, NULL, NULL, NULL);
8180 }
8181 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008182 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008183 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008184 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008185 /*
8186 * And now for the children...
8187 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008188 oldCtxtType = ctxt->ctxtType;
8189 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008190 ctxt->ctxtType = type;
8191 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008192 child = node->children;
8193 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008194 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8195 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008196 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008197 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008198 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8199 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008200 "(annotation?, (restriction | list | union))");
8201 } else if (IS_SCHEMA(child, "restriction")) {
8202 xmlSchemaParseRestriction(ctxt, schema, child,
8203 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008204 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008205 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008206 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008207 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008208 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008209 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008210 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008211 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008212 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008213 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8214 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008215 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008216 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008217 ctxt->parentItem = oldParentItem;
8218 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008219
Daniel Veillard4255d502002-04-16 15:50:10 +00008220 return (type);
8221}
8222
Daniel Veillard4255d502002-04-16 15:50:10 +00008223/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008224 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008225 * @ctxt: a schema validation context
8226 * @schema: the schema being built
8227 * @node: a subtree containing XML Schema informations
8228 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008229 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008230 * *WARNING* this interface is highly subject to change
8231 *
William M. Bracke7091952004-05-11 15:09:58 +00008232 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008233 * 1 in case of success.
8234 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008235static xmlSchemaTreeItemPtr
8236xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8237 xmlSchemaPtr schema,
8238 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008239{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008240 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008241 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008242 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008243 const xmlChar *ref = NULL, *refNs = NULL;
8244 int min, max;
8245
8246 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008247 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008248
8249 attr = xmlSchemaGetPropNode(node, "ref");
8250 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008251 xmlSchemaPMissingAttrErr(ctxt,
8252 XML_SCHEMAP_S4S_ATTR_MISSING,
8253 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008254 "ref", NULL);
8255 return (NULL);
8256 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008257 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008258 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008259 }
8260 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008261 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008262 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008263 /*
8264 * Check for illegal attributes.
8265 */
8266 attr = node->properties;
8267 while (attr != NULL) {
8268 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008269 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008270 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8271 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8272 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008273 xmlSchemaPIllegalAttrErr(ctxt,
8274 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8275 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008276 }
8277 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008278 xmlSchemaPIllegalAttrErr(ctxt,
8279 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8280 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008281 }
8282 attr = attr->next;
8283 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008284 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008285 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8286 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008287 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008288 /*
8289 * Create a reference item as the term; it will be substituted for
8290 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008291 */
8292 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008293 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8294 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8295 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8296 /*
8297 * And now for the children...
8298 */
8299 child = node->children;
8300 /* TODO: Is annotation even allowed for a model group reference? */
8301 if (IS_SCHEMA(child, "annotation")) {
8302 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008303 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008304 */
8305 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8306 child = child->next;
8307 }
8308 if (child != NULL) {
8309 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008310 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008311 NULL, NULL, node, child, NULL,
8312 "(annotation?)");
8313 }
8314 /*
8315 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8316 */
8317 if ((min == 0) && (max == 0))
8318 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008319 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008320 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8321 return ((xmlSchemaTreeItemPtr) item);
8322}
8323
8324/**
8325 * xmlSchemaParseModelGroupDefinition:
8326 * @ctxt: a schema validation context
8327 * @schema: the schema being built
8328 * @node: a subtree containing XML Schema informations
8329 *
8330 * Parses a XML schema model group definition.
8331 * *WARNING* this interface is highly subject to change
8332 *
8333 * Returns -1 in case of error, 0 if the declaration is improper and
8334 * 1 in case of success.
8335 */
8336static xmlSchemaModelGroupDefPtr
8337xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8338 xmlSchemaPtr schema,
8339 xmlNodePtr node)
8340{
8341 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008342 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008343 xmlAttrPtr attr;
8344 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008345
8346 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008347 return (NULL);
8348
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008349 attr = xmlSchemaGetPropNode(node, "name");
8350 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008351 xmlSchemaPMissingAttrErr(ctxt,
8352 XML_SCHEMAP_S4S_ATTR_MISSING,
8353 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008354 "name", NULL);
8355 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008356 } else if (xmlSchemaPValAttrNode(ctxt,
8357 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008358 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8359 return (NULL);
8360 }
8361 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8362 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008363 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008364 /*
8365 * Check for illegal attributes.
8366 */
8367 attr = node->properties;
8368 while (attr != NULL) {
8369 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008370 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008371 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008372 xmlSchemaPIllegalAttrErr(ctxt,
8373 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8374 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008375 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008376 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008377 xmlSchemaPIllegalAttrErr(ctxt,
8378 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8379 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008380 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008381 attr = attr->next;
8382 }
8383 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8384 /*
8385 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008386 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008387 child = node->children;
8388 if (IS_SCHEMA(child, "annotation")) {
8389 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8390 child = child->next;
8391 }
8392 if (IS_SCHEMA(child, "all")) {
8393 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8394 XML_SCHEMA_TYPE_ALL, 0);
8395 child = child->next;
8396 } else if (IS_SCHEMA(child, "choice")) {
8397 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8398 XML_SCHEMA_TYPE_CHOICE, 0);
8399 child = child->next;
8400 } else if (IS_SCHEMA(child, "sequence")) {
8401 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8402 XML_SCHEMA_TYPE_SEQUENCE, 0);
8403 child = child->next;
8404 }
8405 if (child != NULL) {
8406 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008407 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8408 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008409 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008410 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008411
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008412 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008413}
8414
8415/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008416 * xmlSchemaCleanupDoc:
8417 * @ctxt: a schema validation context
8418 * @node: the root of the document.
8419 *
8420 * removes unwanted nodes in a schemas document tree
8421 */
8422static void
8423xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8424{
8425 xmlNodePtr delete, cur;
8426
8427 if ((ctxt == NULL) || (root == NULL)) return;
8428
8429 /*
8430 * Remove all the blank text nodes
8431 */
8432 delete = NULL;
8433 cur = root;
8434 while (cur != NULL) {
8435 if (delete != NULL) {
8436 xmlUnlinkNode(delete);
8437 xmlFreeNode(delete);
8438 delete = NULL;
8439 }
8440 if (cur->type == XML_TEXT_NODE) {
8441 if (IS_BLANK_NODE(cur)) {
8442 if (xmlNodeGetSpacePreserve(cur) != 1) {
8443 delete = cur;
8444 }
8445 }
8446 } else if ((cur->type != XML_ELEMENT_NODE) &&
8447 (cur->type != XML_CDATA_SECTION_NODE)) {
8448 delete = cur;
8449 goto skip_children;
8450 }
8451
8452 /*
8453 * Skip to next node
8454 */
8455 if (cur->children != NULL) {
8456 if ((cur->children->type != XML_ENTITY_DECL) &&
8457 (cur->children->type != XML_ENTITY_REF_NODE) &&
8458 (cur->children->type != XML_ENTITY_NODE)) {
8459 cur = cur->children;
8460 continue;
8461 }
8462 }
8463 skip_children:
8464 if (cur->next != NULL) {
8465 cur = cur->next;
8466 continue;
8467 }
8468
8469 do {
8470 cur = cur->parent;
8471 if (cur == NULL)
8472 break;
8473 if (cur == root) {
8474 cur = NULL;
8475 break;
8476 }
8477 if (cur->next != NULL) {
8478 cur = cur->next;
8479 break;
8480 }
8481 } while (cur != NULL);
8482 }
8483 if (delete != NULL) {
8484 xmlUnlinkNode(delete);
8485 xmlFreeNode(delete);
8486 delete = NULL;
8487 }
8488}
8489
William M. Brack2f2a6632004-08-20 23:09:47 +00008490
8491/**
8492 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008493 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008494 * @ctxt: a schema validation context
8495 * @schemaLocation: an URI defining where to find the imported schema
8496 *
8497 * import a XML schema
8498 * *WARNING* this interface is highly subject to change
8499 *
8500 * Returns -1 in case of error and 1 in case of success.
8501 */
8502#if 0
8503static xmlSchemaImportPtr
8504xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8505 const xmlChar *schemaLocation)
8506{
8507 xmlSchemaImportPtr import;
8508 xmlSchemaParserCtxtPtr newctxt;
8509
8510 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8511 if (newctxt == NULL) {
8512 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8513 NULL);
8514 return (NULL);
8515 }
8516 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8517 /* Keep the same dictionnary for parsing, really */
8518 xmlDictReference(ctxt->dict);
8519 newctxt->dict = ctxt->dict;
8520 newctxt->includes = 0;
8521 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8522
8523 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8524 ctxt->userData);
8525
8526 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8527 if (import == NULL) {
8528 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8529 NULL);
8530 xmlSchemaFreeParserCtxt(newctxt);
8531 return (NULL);
8532 }
8533
8534 memset(import, 0, sizeof(xmlSchemaImport));
8535 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8536 import->schema = xmlSchemaParse(newctxt);
8537
8538 if (import->schema == NULL) {
8539 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008540 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008541 "Failed to import schema from location \"%s\".\n",
8542 schemaLocation, NULL);
8543
8544 xmlSchemaFreeParserCtxt(newctxt);
8545 /* The schemaLocation is held by the dictionary.
8546 if (import->schemaLocation != NULL)
8547 xmlFree((xmlChar *)import->schemaLocation);
8548 */
8549 xmlFree(import);
8550 return NULL;
8551 }
8552
8553 xmlSchemaFreeParserCtxt(newctxt);
8554 return import;
8555}
8556#endif
8557
8558static void
8559xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8560{
8561 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8562 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8563
8564 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8565 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8566
8567 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8568 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8569 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8570 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8571 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8572 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8573 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8574 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8575
8576 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8577 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8578 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8579 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8580 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8581 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8582}
8583
8584static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008585xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008586 xmlSchemaPtr schema,
8587 xmlNodePtr node)
8588{
8589 xmlAttrPtr attr;
8590 const xmlChar *val;
8591
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008592 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8593 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008594 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008595 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8596 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008597 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008598 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8599
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008600 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008601 if (attr != NULL) {
8602 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008604 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008606 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008607 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008608 "(qualified | unqualified)", val, NULL, NULL, NULL);
8609 }
8610 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008611
8612 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008613 if (attr != NULL) {
8614 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008615 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008616 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008617 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008618 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008619 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008620 "(qualified | unqualified)", val, NULL, NULL, NULL);
8621 }
8622 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008623
8624 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008625 if (attr != NULL) {
8626 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8627 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8628 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8629 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8630 -1,
8631 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8632 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8633 xmlSchemaPSimpleTypeErr(ctxt,
8634 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008635 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008636 "(#all | List of (extension | restriction | list | union))",
8637 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008639 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008640
8641 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008642 if (attr != NULL) {
8643 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8644 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8645 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8646 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8647 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8648 xmlSchemaPSimpleTypeErr(ctxt,
8649 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008650 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008651 "(#all | List of (extension | restriction | substitution))",
8652 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008653 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008654 }
8655}
8656
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008657/**
8658 * xmlSchemaParseSchemaTopLevel:
8659 * @ctxt: a schema validation context
8660 * @schema: the schemas
8661 * @nodes: the list of top level nodes
8662 *
8663 * Returns the internal XML Schema structure built from the resource or
8664 * NULL in case of error
8665 */
8666static void
8667xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8668 xmlSchemaPtr schema, xmlNodePtr nodes)
8669{
8670 xmlNodePtr child;
8671 xmlSchemaAnnotPtr annot;
8672
8673 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8674 return;
8675
8676 child = nodes;
8677 while ((IS_SCHEMA(child, "include")) ||
8678 (IS_SCHEMA(child, "import")) ||
8679 (IS_SCHEMA(child, "redefine")) ||
8680 (IS_SCHEMA(child, "annotation"))) {
8681 if (IS_SCHEMA(child, "annotation")) {
8682 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8683 if (schema->annot == NULL)
8684 schema->annot = annot;
8685 else
8686 xmlSchemaFreeAnnot(annot);
8687 } else if (IS_SCHEMA(child, "import")) {
8688 xmlSchemaParseImport(ctxt, schema, child);
8689 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008690 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008691 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008692 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008693 } else if (IS_SCHEMA(child, "redefine")) {
8694 TODO
8695 }
8696 child = child->next;
8697 }
8698 while (child != NULL) {
8699 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008700 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008701 child = child->next;
8702 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008703 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008704 child = child->next;
8705 } else if (IS_SCHEMA(child, "element")) {
8706 xmlSchemaParseElement(ctxt, schema, child, 1);
8707 child = child->next;
8708 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008709 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008710 child = child->next;
8711 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008712 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008713 child = child->next;
8714 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008715 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008716 child = child->next;
8717 } else if (IS_SCHEMA(child, "notation")) {
8718 xmlSchemaParseNotation(ctxt, schema, child);
8719 child = child->next;
8720 } else {
8721 xmlSchemaPErr2(ctxt, NULL, child,
8722 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008723 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008724 child->name, NULL);
8725 child = child->next;
8726 }
8727 while (IS_SCHEMA(child, "annotation")) {
8728 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8729 if (schema->annot == NULL)
8730 schema->annot = annot;
8731 else
8732 xmlSchemaFreeAnnot(annot);
8733 child = child->next;
8734 }
8735 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008736 ctxt->parentItem = NULL;
8737 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008738}
8739
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008740static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008741xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008742 xmlHashTablePtr *imports,
8743 const xmlChar *nsName)
8744{
8745 xmlSchemaImportPtr ret;
8746
8747 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008748 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008749 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008750 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008751 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8752 NULL, NULL, (xmlNodePtr) ctxt->doc,
8753 "Internal error: failed to build the import table",
8754 NULL);
8755 return (NULL);
8756 }
8757 }
8758 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8759 if (ret == NULL) {
8760 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8761 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008762 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008763 memset(ret, 0, sizeof(xmlSchemaImport));
8764 if (nsName == NULL)
8765 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008766 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008767
8768 return (ret);
8769}
8770
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008771/**
8772 * xmlSchemaNewParserCtxtUseDict:
8773 * @URL: the location of the schema
8774 * @dict: the dictionary to be used
8775 *
8776 * Create an XML Schemas parse context for that file/resource expected
8777 * to contain an XML Schemas file.
8778 *
8779 * Returns the parser context or NULL in case of error
8780 */
8781static xmlSchemaParserCtxtPtr
8782xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8783{
8784 xmlSchemaParserCtxtPtr ret;
8785 /*
8786 if (URL == NULL)
8787 return (NULL);
8788 */
8789
8790 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8791 if (ret == NULL) {
8792 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8793 NULL);
8794 return (NULL);
8795 }
8796 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8797 ret->dict = dict;
8798 xmlDictReference(dict);
8799 if (URL != NULL)
8800 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8801 ret->includes = 0;
8802 return (ret);
8803}
8804
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008805static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008806xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8807{
8808 if (vctxt->pctxt == NULL) {
8809 if (vctxt->schema != NULL)
8810 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8811 else
8812 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8813 if (vctxt->pctxt == NULL) {
8814 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8815 "failed to create a temp. parser context");
8816 return (-1);
8817 }
8818 /* TODO: Pass user data. */
8819 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8820 }
8821 return (0);
8822}
8823
8824static int
8825xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008826 xmlSchemaPtr schema,
8827 xmlNodePtr node,
8828 const xmlChar *nsName,
8829 const xmlChar *location,
8830 xmlDocPtr *doc,
8831 const xmlChar **targetNamespace,
8832 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008833{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008834 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008835 xmlParserCtxtPtr parserCtxt;
8836 xmlSchemaImportPtr import;
8837 const xmlChar *ns;
8838 xmlNodePtr root;
8839
8840 /*
8841 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8842 * <xsi:noNamespaceSchemaLocation>.
8843 */
8844 *doc = NULL;
8845 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008846 * Given that the schemaLocation [attribute] is only a hint, it is open
8847 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008848 * namespace, regardless of the ·actual value· of schemaLocation, but
8849 * such a strategy risks missing useful information when new
8850 * schemaLocations are offered.
8851 *
8852 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8853 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8854 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008855 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008856 */
8857 if (location == NULL) {
8858 /*
8859 * Schema Document Location Strategy:
8860 *
8861 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008862 * either as a resource which is an XML document or a <schema> element
8863 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008864 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008865 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008866 *
8867 * NOTE: Those stategies are not supported, so we will skip.
8868 */
8869 return (0);
8870 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008871 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008872 ns = XML_SCHEMAS_NO_NAMESPACE;
8873 else
8874 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008875
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008876 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008877 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008878 /*
8879 * There was a valid resource for the specified namespace already
8880 * defined, so skip.
8881 * TODO: This might be changed someday to allow import of
8882 * components from multiple documents for a single target namespace.
8883 */
8884 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008885 }
8886 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8887 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8888 else {
8889 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8890 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8891 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008892 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008893 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008894 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008895 * 2 Based on the location URI, identify an existing schema document,
8896 * either as a resource which is an XML document or a <schema> element
8897 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008898 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008899 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008900 * web which is or contains or references a <schema> element;
8901 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8902 *
8903 */
8904 if ((absolute == 0) && (node != NULL)) {
8905 xmlChar *base, *URI;
8906
8907 base = xmlNodeGetBase(node->doc, node);
8908 if (base == NULL) {
8909 URI = xmlBuildURI(location, node->doc->URL);
8910 } else {
8911 URI = xmlBuildURI(location, base);
8912 xmlFree(base);
8913 }
8914 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008915 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008916 xmlFree(URI);
8917 }
8918 }
8919 parserCtxt = xmlNewParserCtxt();
8920 if (parserCtxt == NULL) {
8921 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8922 "allocating a parser context", NULL);
8923 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008924 }
8925 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008926 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008927 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008928 xmlDictReference(parserCtxt->dict);
8929 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008930 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008931 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008932 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008933 * 2.1 The referent is (a fragment of) a resource which is an
8934 * XML document (see clause 1.1), which in turn corresponds to
8935 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008936 * set, which in turn corresponds to a valid schema.
8937 * TODO: What to do with the "fragment" stuff?
8938 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008939 * 2.2 The referent is a <schema> element information item in
8940 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008941 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008942 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008943 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008944 */
8945 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008946 xmlErrorPtr lerr;
8947 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008948 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008949 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008950 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008951 * If the doc is NULL and the parser error is an IO error we
8952 * will assume that the resource could not be located or accessed.
8953 *
8954 * TODO: Try to find specific error codes to react only on
8955 * localisation failures.
8956 *
8957 * TODO, FIXME: Check the spec: is a namespace added to the imported
8958 * namespaces, even if the schemaLocation did not provide
8959 * a resource? I guess so, since omitting the "schemaLocation"
8960 * attribute, imports a namespace as well.
8961 */
8962 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008963 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008964 xmlFreeParserCtxt(parserCtxt);
8965 return(0);
8966 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008968 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008969 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008970 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008971 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008972 xmlFreeParserCtxt(parserCtxt);
8973 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8974 }
8975 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008976
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008977 root = xmlDocGetRootElement(*doc);
8978 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008979 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008980 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008981 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008982 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008983 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008984 xmlFreeDoc(*doc);
8985 *doc = NULL;
8986 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008987 }
8988
8989 xmlSchemaCleanupDoc(pctxt, root);
8990
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008991 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008994 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008995 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008996 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008997 xmlFreeDoc(*doc);
8998 *doc = NULL;
8999 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009000 }
9001 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009002 /*
9003 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009004 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009005 if (nsName == NULL) {
9006 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009007 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009008 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009009 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009010 "The XML schema to be imported is not expected "
9011 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009012 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009013 xmlFreeDoc(*doc);
9014 *doc = NULL;
9015 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9016 }
9017 } else {
9018 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009019 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009020 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009021 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009022 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009023 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009024 xmlFreeDoc(*doc);
9025 *doc = NULL;
9026 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9027 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009028 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009029 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009030 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009031 "The XML schema to be imported is expected to have a "
9032 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009033 "its target namespace of '%s'",
9034 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009035 xmlFreeDoc(*doc);
9036 *doc = NULL;
9037 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9038 }
9039 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009040 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009041 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009042 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9043 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009044 xmlFreeDoc(*doc);
9045 *doc = NULL;
9046 return (-1);
9047 }
9048 import->schemaLocation = location;
9049 import->doc = *doc;
9050 return (0);
9051}
William M. Brack2f2a6632004-08-20 23:09:47 +00009052
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009053static void
9054xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9055 xmlSchemaPtr schema,
9056 const xmlChar *targetNamespace,
9057 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009058{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009059 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009060 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009061
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009062 /*
9063 * Save and reset the context & schema.
9064 */
9065 oldURL = pctxt->URL;
9066 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009067 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009068 oldLocImps = pctxt->localImports;
9069 pctxt->localImports = NULL;
9070 oldNumLocImps = pctxt->nbLocalImports;
9071 pctxt->nbLocalImports = 0;
9072 oldSizeLocImps = pctxt->sizeLocalImports;
9073 pctxt->sizeLocalImports = 0;
9074 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009075 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009076 xmlSchemaClearSchemaDefaults(schema);
9077 oldTNS = schema->targetNamespace;
9078 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009079 if ((targetNamespace != NULL) &&
9080 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9081 /*
9082 * We are parsing the schema for schema!
9083 */
9084 pctxt->isS4S = 1;
9085 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009086 /*
9087 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009088 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009089 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9090 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9091 /*
9092 * Restore the context & schema.
9093 */
9094 schema->flags = oldFlags;
9095 schema->targetNamespace = oldTNS;
9096 if (pctxt->localImports != NULL)
9097 xmlFree((xmlChar *) pctxt->localImports);
9098 pctxt->localImports = oldLocImps;
9099 pctxt->nbLocalImports = oldNumLocImps;
9100 pctxt->sizeLocalImports = oldSizeLocImps;
9101 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009102 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009103}
9104
William M. Brack2f2a6632004-08-20 23:09:47 +00009105/**
9106 * xmlSchemaParseImport:
9107 * @ctxt: a schema validation context
9108 * @schema: the schema being built
9109 * @node: a subtree containing XML Schema informations
9110 *
9111 * parse a XML schema Import definition
9112 * *WARNING* this interface is highly subject to change
9113 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009114 * Returns 0 in case of success, a positive error code if
9115 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009116 */
9117static int
9118xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9119 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009120{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009121 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009122 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009123 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009124 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009125 xmlAttrPtr attr;
9126 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009127 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009128
9129 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9130 return (-1);
9131
9132 /*
9133 * Check for illegal attributes.
9134 */
9135 attr = node->properties;
9136 while (attr != NULL) {
9137 if (attr->ns == NULL) {
9138 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9139 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9140 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009141 xmlSchemaPIllegalAttrErr(ctxt,
9142 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9143 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009144 }
9145 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009146 xmlSchemaPIllegalAttrErr(ctxt,
9147 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9148 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009149 }
9150 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009151 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009152 /*
9153 * Extract and validate attributes.
9154 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009155 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9156 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009157 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009158 xmlSchemaPSimpleTypeErr(ctxt,
9159 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9160 NULL, node,
9161 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009162 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009163 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9164 }
9165
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009166 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9167 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009168 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009169 xmlSchemaPSimpleTypeErr(ctxt,
9170 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9171 NULL, node,
9172 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009173 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009174 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009175 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009176 /*
9177 * And now for the children...
9178 */
9179 child = node->children;
9180 if (IS_SCHEMA(child, "annotation")) {
9181 /*
9182 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009183 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009184 */
9185 child = child->next;
9186 }
9187 if (child != NULL) {
9188 xmlSchemaPContentErr(ctxt,
9189 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9190 NULL, NULL, node, child, NULL,
9191 "(annotation?)");
9192 }
9193 /*
9194 * Apply additional constraints.
9195 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009196 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009197 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009198 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9199 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009200 * targetNamespace [attribute].
9201 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009202 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009203 xmlSchemaPCustomErr(ctxt,
9204 XML_SCHEMAP_SRC_IMPORT_1_1,
9205 NULL, NULL, node,
9206 "The value of the attribute 'namespace' must not match "
9207 "the target namespace '%s' of the importing schema",
9208 schema->targetNamespace);
9209 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9210 }
9211 } else {
9212 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009213 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009214 * <schema> must have a targetNamespace [attribute].
9215 */
9216 if (schema->targetNamespace == NULL) {
9217 xmlSchemaPCustomErr(ctxt,
9218 XML_SCHEMAP_SRC_IMPORT_1_2,
9219 NULL, NULL, node,
9220 "The attribute 'namespace' must be existent if "
9221 "the importing schema has no target namespace",
9222 NULL);
9223 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9224 }
9225 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009226 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009227 * Add the namespace to the list of locally imported namespace.
9228 */
9229 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009230 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009231 sizeof(const xmlChar*));
9232 ctxt->sizeLocalImports = 10;
9233 ctxt->nbLocalImports = 0;
9234 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9235 ctxt->sizeLocalImports *= 2;
9236 ctxt->localImports = (const xmlChar **) xmlRealloc(
9237 (xmlChar **) ctxt->localImports,
9238 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9239 }
9240 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9241 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009242 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009243 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009244 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9245 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009246 schemaLocation, &doc, &targetNamespace, 0);
9247 if (ret != 0) {
9248 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009249 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009250 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009251 } else if (doc != NULL) {
9252 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9253 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009254 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009255
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009256 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009257}
9258
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009259/**
9260 * xmlSchemaParseInclude:
9261 * @ctxt: a schema validation context
9262 * @schema: the schema being built
9263 * @node: a subtree containing XML Schema informations
9264 *
9265 * parse a XML schema Include definition
9266 *
William M. Bracke7091952004-05-11 15:09:58 +00009267 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009268 * 1 in case of success.
9269 */
9270static int
9271xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9272 xmlNodePtr node)
9273{
9274 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009275 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009276 xmlDocPtr doc = NULL;
9277 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009278 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009279 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009280 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009281 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009282
9283
9284 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9285 return (-1);
9286
9287 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009288 * Check for illegal attributes.
9289 */
9290 attr = node->properties;
9291 while (attr != NULL) {
9292 if (attr->ns == NULL) {
9293 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9294 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009295 xmlSchemaPIllegalAttrErr(ctxt,
9296 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9297 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009298 }
9299 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009300 xmlSchemaPIllegalAttrErr(ctxt,
9301 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9302 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009303 }
9304 attr = attr->next;
9305 }
9306 /*
9307 * Extract and validate attributes.
9308 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009309 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009310 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009311 * Preliminary step, extract the URI-Reference for the include and
9312 * make an URI from the base.
9313 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009314 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9315 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009316 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009317 xmlChar *uri = NULL;
9318
9319 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9320 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009321 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009322 base = xmlNodeGetBase(node->doc, node);
9323 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009324 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009325 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009326 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009327 xmlFree(base);
9328 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009329 if (uri == NULL) {
9330 xmlSchemaPErr(ctxt,
9331 node,
9332 XML_SCHEMAP_INTERNAL,
9333 "Internal error: xmlSchemaParseInclude, "
9334 "could not build an URI from the schemaLocation.\n",
9335 NULL, NULL);
9336 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009337 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009338 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9339 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009340 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009341 xmlSchemaPMissingAttrErr(ctxt,
9342 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9343 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009344 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009345 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009346 /*
9347 * And now for the children...
9348 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009349 child = node->children;
9350 while (IS_SCHEMA(child, "annotation")) {
9351 /*
9352 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009353 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009354 */
9355 child = child->next;
9356 }
9357 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009358 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009359 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9360 NULL, NULL, node, child, NULL,
9361 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009362 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009363 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009364 * Report self-inclusion.
9365 */
9366 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9367 xmlSchemaPCustomErr(ctxt,
9368 XML_SCHEMAP_SRC_INCLUDE,
9369 NULL, NULL, node,
9370 "The schema document '%s' cannot include itself.",
9371 schemaLocation);
9372 return (XML_SCHEMAP_SRC_INCLUDE);
9373 }
9374 /*
9375 * Check if this one was already processed to avoid incorrect
9376 * duplicate component errors and infinite circular inclusion.
9377 */
9378 include = schema->includes;
9379 while (include != NULL) {
9380 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9381 targetNamespace = include->origTargetNamespace;
9382 if (targetNamespace == NULL) {
9383 /*
9384 * Chameleon include: skip only if it was build for
9385 * the targetNamespace of the including schema.
9386 */
9387 if (xmlStrEqual(schema->targetNamespace,
9388 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009389 goto check_targetNamespace;
9390 }
9391 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009392 goto check_targetNamespace;
9393 }
9394 }
9395 include = include->next;
9396 }
9397 /*
9398 * First step is to parse the input document into an DOM/Infoset
9399 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009400 */
9401 parserCtxt = xmlNewParserCtxt();
9402 if (parserCtxt == NULL) {
9403 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9404 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009405 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009406 }
9407
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009408 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9409 xmlDictFree(parserCtxt->dict);
9410 parserCtxt->dict = ctxt->dict;
9411 xmlDictReference(parserCtxt->dict);
9412 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009413
9414 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009415 NULL, SCHEMAS_PARSE_OPTIONS);
9416 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009417 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009418 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009419 * TODO: It is not an error for the ·actual value· of the
9420 * schemaLocation [attribute] to fail to resolve it all, in which
9421 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009422 * So do we need a warning report here?
9423 */
9424 xmlSchemaPCustomErr(ctxt,
9425 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009426 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009427 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009428 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009429 }
9430
9431 /*
9432 * Then extract the root of the schema
9433 */
9434 root = xmlDocGetRootElement(doc);
9435 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009436 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009437 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009438 NULL, NULL, node,
9439 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009440 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009441 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009442 }
9443
9444 /*
9445 * Remove all the blank text nodes
9446 */
9447 xmlSchemaCleanupDoc(ctxt, root);
9448
9449 /*
9450 * Check the schemas top level element
9451 */
9452 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009453 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009454 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009455 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009456 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009457 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009458 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009459 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009460
William M. Brack2f2a6632004-08-20 23:09:47 +00009461 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009462 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009463 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9464 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009465 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9466 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009467check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009468 if (targetNamespace != NULL) {
9469 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009470 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009471 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009472 NULL, NULL, node,
9473 "The target namespace of the included schema "
9474 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009475 "has no target namespace",
9476 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009477 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009478 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9479 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009480 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009481 NULL, NULL, node,
9482 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009483 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009484 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009485 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009486 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009487 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009488 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009489 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009490 } else
9491 wasConvertingNs = 1;
9492 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009493
9494 if (include != NULL)
9495 goto exit;
9496
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009497 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009498 * URGENT TODO: If the schema is a chameleon-include then copy the
9499 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009500 * of those components, do nothing otherwise.
9501 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009502 * for every destinct including targetNamespace; thus not performant at
9503 * the moment.
9504 * TODO: Check when the namespace in wildcards for chameleons needs
9505 * to be converted: before we built wildcard intersections or after.
9506 */
9507 /*
9508 * Register the include.
9509 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009510 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9511 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009512 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9513 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009514 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009515 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009516 include->next = schema->includes;
9517 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009518 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009519 * TODO: Use the resolved URI for the this location, since it might
9520 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009521 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009522 include->schemaLocation = schemaLocation;
9523 include->doc = doc;
9524 /*
9525 * In case of chameleons, the original target namespace will differ
9526 * from the resulting namespace.
9527 */
9528 include->origTargetNamespace = targetNamespace;
9529 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009530#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009531 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009532 xmlGenericError(xmlGenericErrorContext,
9533 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9534 " into TNS '%s'\n", schemaLocation,
9535 targetNamespace, schema->targetNamespace);
9536 else
9537 xmlGenericError(xmlGenericErrorContext,
9538 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9539 targetNamespace);
9540#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009541 /*
9542 * Compile the included schema.
9543 */
9544 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9545
9546exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009547 /*
9548 * Remove the converting flag.
9549 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009550 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009551 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009552 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009553 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009554
9555exit_invalid:
9556 if (doc != NULL) {
9557 if (include != NULL)
9558 include->doc = NULL;
9559 xmlFreeDoc(doc);
9560 }
9561 return (ctxt->err);
9562
9563exit_failure:
9564 if (doc != NULL) {
9565 if (include != NULL)
9566 include->doc = NULL;
9567 xmlFreeDoc(doc);
9568 }
9569 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009570}
9571
9572/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009573 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009574 * @ctxt: a schema validation context
9575 * @schema: the schema being built
9576 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009577 * @type: the "compositor" type
9578 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009579 *
9580 * parse a XML schema Sequence definition
9581 * *WARNING* this interface is highly subject to change
9582 *
William M. Bracke7091952004-05-11 15:09:58 +00009583 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009584 * 1 in case of success.
9585 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009586static xmlSchemaTreeItemPtr
9587xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9588 xmlNodePtr node, xmlSchemaTypeType type,
9589 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009590{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009591 xmlSchemaModelGroupPtr item;
9592 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009593 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009594 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009595 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009596 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009597
9598 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009599 return (NULL);
9600 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009601 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009602 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009603 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9604 if (item == NULL)
9605 return (NULL);
9606
9607 if (withParticle) {
9608 if (type == XML_SCHEMA_TYPE_ALL) {
9609 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009610 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009611 } else {
9612 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009613 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9614 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9615 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009616 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009617 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9618 /*
9619 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009620 */
9621 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9622 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009623 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009624 particle->children = (xmlSchemaTreeItemPtr) item;
9625 /*
9626 * Check for illegal attributes.
9627 */
9628 attr = node->properties;
9629 while (attr != NULL) {
9630 if (attr->ns == NULL) {
9631 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9632 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9633 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009634 xmlSchemaPIllegalAttrErr(ctxt,
9635 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9636 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009637 }
9638 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009639 xmlSchemaPIllegalAttrErr(ctxt,
9640 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9641 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009642 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009643 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009644 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009645 } else {
9646 /*
9647 * Check for illegal attributes.
9648 */
9649 attr = node->properties;
9650 while (attr != NULL) {
9651 if (attr->ns == NULL) {
9652 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009653 xmlSchemaPIllegalAttrErr(ctxt,
9654 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9655 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009656 }
9657 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009658 xmlSchemaPIllegalAttrErr(ctxt,
9659 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9660 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009661 }
9662 attr = attr->next;
9663 }
9664
William M. Brack2f2a6632004-08-20 23:09:47 +00009665 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009666
William M. Brack2f2a6632004-08-20 23:09:47 +00009667 /*
9668 * Extract and validate attributes.
9669 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009670 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009671 /*
9672 * And now for the children...
9673 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009674 child = node->children;
9675 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009676 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009677 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009678 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009679 oldcontainer = ctxt->container;
9680 ctxt->container = container;
9681 if (type == XML_SCHEMA_TYPE_ALL) {
9682 xmlSchemaParticlePtr part, last = NULL;
9683
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009684 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009685 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9686 schema, child, 0);
9687 if (part != NULL) {
9688 if (part->minOccurs > 1)
9689 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009690 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009691 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9692 if (part->maxOccurs > 1)
9693 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009694 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009695 "Invalid value for maxOccurs (must be 0 or 1)",
9696 NULL);
9697 if (last == NULL)
9698 item->children = (xmlSchemaTreeItemPtr) part;
9699 else
9700 last->next = (xmlSchemaTreeItemPtr) part;
9701 last = part;
9702 }
9703 child = child->next;
9704 }
9705 if (child != NULL) {
9706 xmlSchemaPContentErr(ctxt,
9707 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9708 NULL, NULL, node, child, NULL,
9709 "(annotation?, (annotation?, element*)");
9710 }
9711 } else {
9712 /* choice + sequence */
9713 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9714
9715 while ((IS_SCHEMA(child, "element")) ||
9716 (IS_SCHEMA(child, "group")) ||
9717 (IS_SCHEMA(child, "any")) ||
9718 (IS_SCHEMA(child, "choice")) ||
9719 (IS_SCHEMA(child, "sequence"))) {
9720
9721 if (IS_SCHEMA(child, "element")) {
9722 part = (xmlSchemaTreeItemPtr)
9723 xmlSchemaParseElement(ctxt, schema, child, 0);
9724 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009725 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009726 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9727 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009728 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009729 xmlSchemaParseAny(ctxt, schema, child);
9730 } else if (IS_SCHEMA(child, "choice")) {
9731 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9732 XML_SCHEMA_TYPE_CHOICE, 1);
9733 } else if (IS_SCHEMA(child, "sequence")) {
9734 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9735 XML_SCHEMA_TYPE_SEQUENCE, 1);
9736 }
9737 if (part != NULL) {
9738 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009739 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009740 else
9741 last->next = part;
9742 last = part;
9743 }
9744 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009745 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009746 if (child != NULL) {
9747 xmlSchemaPContentErr(ctxt,
9748 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9749 NULL, NULL, node, child, NULL,
9750 "(annotation?, (element | group | choice | sequence | any)*)");
9751 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009752 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009753 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009754 if (withParticle) {
9755 if ((min == 0) && (max == 0))
9756 return (NULL);
9757 else
9758 return ((xmlSchemaTreeItemPtr) particle);
9759 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009760 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009761}
9762
9763/**
9764 * xmlSchemaParseRestriction:
9765 * @ctxt: a schema validation context
9766 * @schema: the schema being built
9767 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009768 *
9769 * parse a XML schema Restriction definition
9770 * *WARNING* this interface is highly subject to change
9771 *
9772 * Returns the type definition or NULL in case of error
9773 */
9774static xmlSchemaTypePtr
9775xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009776 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009777{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009778 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009779 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009780 char buf[30];
9781 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009782 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009783
9784 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9785 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009786 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009787 type = ctxt->ctxtType;
9788 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009789
9790 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009791 * TODO: Is the container needed at all? the anonymous
9792 * items inside should generate unique names already.
9793 */
9794 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009795 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009796 /*
9797 * Check for illegal attributes.
9798 */
9799 attr = node->properties;
9800 while (attr != NULL) {
9801 if (attr->ns == NULL) {
9802 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9803 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009804 xmlSchemaPIllegalAttrErr(ctxt,
9805 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9806 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009807 }
9808 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009809 xmlSchemaPIllegalAttrErr(ctxt,
9810 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9811 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009812 }
9813 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009814 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009815 /*
9816 * Extract and validate attributes.
9817 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009818 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009819 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009820 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009821 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009822 /*
9823 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9824 * among its [children]), the simple type definition which is
9825 * the {content type} of the type definition ·resolved· to by
9826 * the ·actual value· of the base [attribute]"
9827 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009828 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009829 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009830 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009831 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009832 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009833 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009834 XML_SCHEMAP_S4S_ATTR_MISSING,
9835 type, node, "base", NULL);
9836 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009837 /*
9838 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009839 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009840 child = node->children;
9841 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009842 /*
9843 * Add the annotation to the simple type ancestor.
9844 */
9845 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9846 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009847 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009848 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009849 oldcontainer = ctxt->container;
9850 ctxt->container = container;
9851 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9852 /*
9853 * Corresponds to <simpleType><restriction><simpleType>.
9854 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009855 if (IS_SCHEMA(child, "simpleType")) {
9856 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009857 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009858 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009859 * Either the base [attribute] or the simpleType [child] of the
9860 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009861 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009862 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009863 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009864 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009865 "The attribute 'base' and the <simpleType> child are "
9866 "mutually exclusive", NULL);
9867 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009868 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009869 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009870 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009871 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009872 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009873 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009874 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9875 NULL, NULL, node, child,
9876 "Either the attribute 'base' or a <simpleType> child "
9877 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009878 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009879 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9880 /*
9881 * Corresponds to <complexType><complexContent><restriction>...
9882 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009883 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009884 * Model groups <all>, <choice> and <sequence>.
9885 */
9886 if (IS_SCHEMA(child, "all")) {
9887 type->subtypes = (xmlSchemaTypePtr)
9888 xmlSchemaParseModelGroup(ctxt, schema, child,
9889 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009890 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009891 } else if (IS_SCHEMA(child, "choice")) {
9892 type->subtypes = (xmlSchemaTypePtr)
9893 xmlSchemaParseModelGroup(ctxt,
9894 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9895 child = child->next;
9896 } else if (IS_SCHEMA(child, "sequence")) {
9897 type->subtypes = (xmlSchemaTypePtr)
9898 xmlSchemaParseModelGroup(ctxt, schema, child,
9899 XML_SCHEMA_TYPE_SEQUENCE, 1);
9900 child = child->next;
9901 /*
9902 * Model group reference <group>.
9903 */
9904 } else if (IS_SCHEMA(child, "group")) {
9905 type->subtypes = (xmlSchemaTypePtr)
9906 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9907 child = child->next;
9908 }
9909 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009910 /*
9911 * Corresponds to <complexType><simpleContent><restriction>...
9912 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009913 * "1.1 the simple type definition corresponding to the <simpleType>
9914 * among the [children] of <restriction> if there is one;"
9915 */
9916 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009917 /*
9918 * We will store the to-be-restricted simple type in
9919 * type->contentTypeDef *temporarily*.
9920 */
9921 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009922 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009923 if ( type->contentTypeDef == NULL)
9924 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009925 child = child->next;
9926 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009927 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009928
9929 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009930 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009931 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009932 /*
9933 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009934 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009935 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009936
Daniel Veillard01fa6152004-06-29 17:04:39 +00009937 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009938 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009939 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009940 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009941 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9942 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009943 * *Single Facet Value*
9944 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009945 while ((IS_SCHEMA(child, "minInclusive")) ||
9946 (IS_SCHEMA(child, "minExclusive")) ||
9947 (IS_SCHEMA(child, "maxInclusive")) ||
9948 (IS_SCHEMA(child, "maxExclusive")) ||
9949 (IS_SCHEMA(child, "totalDigits")) ||
9950 (IS_SCHEMA(child, "fractionDigits")) ||
9951 (IS_SCHEMA(child, "pattern")) ||
9952 (IS_SCHEMA(child, "enumeration")) ||
9953 (IS_SCHEMA(child, "whiteSpace")) ||
9954 (IS_SCHEMA(child, "length")) ||
9955 (IS_SCHEMA(child, "maxLength")) ||
9956 (IS_SCHEMA(child, "minLength"))) {
9957 facet = xmlSchemaParseFacet(ctxt, schema, child);
9958 if (facet != NULL) {
9959 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009960 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009961 else
9962 lastfacet->next = facet;
9963 lastfacet = facet;
9964 lastfacet->next = NULL;
9965 }
9966 child = child->next;
9967 }
9968 /*
9969 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009970 */
9971 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009972 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9973
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009974 facet = type->facets;
9975 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009976 facetLink = (xmlSchemaFacetLinkPtr)
9977 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009978 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009979 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009980 xmlFree(facetLink);
9981 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009982 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009983 facetLink->facet = facet;
9984 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009985 if (lastFacetLink == NULL)
9986 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009987 else
9988 lastFacetLink->next = facetLink;
9989 lastFacetLink = facetLink;
9990 facet = facet->next;
9991 } while (facet != NULL);
9992 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009993 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009994 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9995 /*
9996 * Attribute uses/declarations.
9997 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009998 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009999 /*
10000 * Attribute wildcard.
10001 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010002 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010003 type->attributeWildcard =
10004 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010005 child = child->next;
10006 }
10007 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010008 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010009 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10010 xmlSchemaPContentErr(ctxt,
10011 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010012 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010013 "annotation?, (group | all | choice | sequence)?, "
10014 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010015 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010016 xmlSchemaPContentErr(ctxt,
10017 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010018 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010019 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10020 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10021 "length | minLength | maxLength | enumeration | whiteSpace | "
10022 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10023 } else {
10024 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010025 xmlSchemaPContentErr(ctxt,
10026 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010027 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010028 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10029 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10030 "length | minLength | maxLength | enumeration | whiteSpace | "
10031 "pattern)*))");
10032 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010033 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010034 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010035 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010036}
10037
10038/**
10039 * xmlSchemaParseExtension:
10040 * @ctxt: a schema validation context
10041 * @schema: the schema being built
10042 * @node: a subtree containing XML Schema informations
10043 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010044 * Parses an <extension>, which is found inside a
10045 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010046 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010047 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010048 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010049 */
10050static xmlSchemaTypePtr
10051xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010052 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010053{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010054 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010055 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010056 char buf[30];
10057 const xmlChar *oldcontainer, *container;
10058 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010059
10060 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10061 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010062 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010063 type = ctxt->ctxtType;
10064 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010065
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010066 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10067 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10068 /*
10069 * Check for illegal attributes.
10070 */
10071 attr = node->properties;
10072 while (attr != NULL) {
10073 if (attr->ns == NULL) {
10074 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10075 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010076 xmlSchemaPIllegalAttrErr(ctxt,
10077 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10078 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010079 }
10080 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010081 xmlSchemaPIllegalAttrErr(ctxt,
10082 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10083 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010084 }
10085 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010086 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010087
10088 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010089
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010090 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010091 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010092 */
10093 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010094 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10095 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010096 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010097 XML_SCHEMAP_S4S_ATTR_MISSING,
10098 NULL, node, "base", NULL);
10099 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010100 /*
10101 * And now for the children...
10102 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010103 child = node->children;
10104 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010105 /*
10106 * Add the annotation to the type ancestor.
10107 */
10108 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10109 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010110 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010111 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010112 oldcontainer = ctxt->container;
10113 ctxt->container = container;
10114 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10115 /*
10116 * Corresponds to <complexType><complexContent><extension>... and:
10117 *
10118 * Model groups <all>, <choice>, <sequence> and <group>.
10119 */
10120 if (IS_SCHEMA(child, "all")) {
10121 type->subtypes = (xmlSchemaTypePtr)
10122 xmlSchemaParseModelGroup(ctxt, schema,
10123 child, XML_SCHEMA_TYPE_ALL, 1);
10124 child = child->next;
10125 } else if (IS_SCHEMA(child, "choice")) {
10126 type->subtypes = (xmlSchemaTypePtr)
10127 xmlSchemaParseModelGroup(ctxt, schema,
10128 child, XML_SCHEMA_TYPE_CHOICE, 1);
10129 child = child->next;
10130 } else if (IS_SCHEMA(child, "sequence")) {
10131 type->subtypes = (xmlSchemaTypePtr)
10132 xmlSchemaParseModelGroup(ctxt, schema,
10133 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10134 child = child->next;
10135 } else if (IS_SCHEMA(child, "group")) {
10136 type->subtypes = (xmlSchemaTypePtr)
10137 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10138 child = child->next;
10139 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010140 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010141 if (child != NULL) {
10142 /*
10143 * Attribute uses/declarations.
10144 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010145 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010146 /*
10147 * Attribute wildcard.
10148 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010149 if (IS_SCHEMA(child, "anyAttribute")) {
10150 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010151 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10152 child = child->next;
10153 }
10154 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010155 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010156 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10157 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010158 xmlSchemaPContentErr(ctxt,
10159 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010160 NULL, NULL, node, child, NULL,
10161 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010162 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010163 } else {
10164 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010165 xmlSchemaPContentErr(ctxt,
10166 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010167 NULL, NULL, node, child, NULL,
10168 "(annotation?, ((attribute | attributeGroup)*, "
10169 "anyAttribute?))");
10170 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010171 }
10172 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010173 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010174}
10175
10176/**
10177 * xmlSchemaParseSimpleContent:
10178 * @ctxt: a schema validation context
10179 * @schema: the schema being built
10180 * @node: a subtree containing XML Schema informations
10181 *
10182 * parse a XML schema SimpleContent definition
10183 * *WARNING* this interface is highly subject to change
10184 *
10185 * Returns the type definition or NULL in case of error
10186 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010187static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010188xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10189 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010190{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010191 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010192 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010193 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010194
10195 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010196 return (-1);
10197 /* Not a component, don't create it. */
10198 type = ctxt->ctxtType;
10199 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10200 /*
10201 * Check for illegal attributes.
10202 */
10203 attr = node->properties;
10204 while (attr != NULL) {
10205 if (attr->ns == NULL) {
10206 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010207 xmlSchemaPIllegalAttrErr(ctxt,
10208 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10209 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010210 }
10211 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010212 xmlSchemaPIllegalAttrErr(ctxt,
10213 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10214 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010215 }
10216 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010217 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010218
10219 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010220
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010221 /*
10222 * And now for the children...
10223 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010224 child = node->children;
10225 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010226 /*
10227 * Add the annotation to the complex type ancestor.
10228 */
10229 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10230 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010231 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010232 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010233 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010234 xmlSchemaParseRestriction(ctxt, schema, child,
10235 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010236 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010237 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010238 xmlSchemaParseExtension(ctxt, schema, child,
10239 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010240 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010241 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010242 if (child != NULL) {
10243 xmlSchemaPContentErr(ctxt,
10244 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010245 NULL, NULL, node, child, NULL,
10246 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010247 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010248 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010249}
10250
10251/**
10252 * xmlSchemaParseComplexContent:
10253 * @ctxt: a schema validation context
10254 * @schema: the schema being built
10255 * @node: a subtree containing XML Schema informations
10256 *
10257 * parse a XML schema ComplexContent definition
10258 * *WARNING* this interface is highly subject to change
10259 *
10260 * Returns the type definition or NULL in case of error
10261 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010262static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010263xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10264 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010265{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010266 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010267 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010268 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010269
10270 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010271 return (-1);
10272 /* Not a component, don't create it. */
10273 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010274 /*
10275 * Check for illegal attributes.
10276 */
10277 attr = node->properties;
10278 while (attr != NULL) {
10279 if (attr->ns == NULL) {
10280 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010281 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010282 {
10283 xmlSchemaPIllegalAttrErr(ctxt,
10284 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10285 NULL, NULL, attr);
10286 }
10287 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10288 xmlSchemaPIllegalAttrErr(ctxt,
10289 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10290 NULL, NULL, attr);
10291 }
10292 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010293 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010294
10295 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10296
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010297 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010298 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010299 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010300 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10301 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10302 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010303 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010304 child = node->children;
10305 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010306 /*
10307 * Add the annotation to the complex type ancestor.
10308 */
10309 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10310 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010311 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010312 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010313 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010314 xmlSchemaParseRestriction(ctxt, schema, child,
10315 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010316 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010317 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010318 xmlSchemaParseExtension(ctxt, schema, child,
10319 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010320 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010321 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010322 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010323 xmlSchemaPContentErr(ctxt,
10324 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10325 NULL, NULL, node, child,
10326 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010327 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010328 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010329}
10330
10331/**
10332 * xmlSchemaParseComplexType:
10333 * @ctxt: a schema validation context
10334 * @schema: the schema being built
10335 * @node: a subtree containing XML Schema informations
10336 *
10337 * parse a XML schema Complex Type definition
10338 * *WARNING* this interface is highly subject to change
10339 *
10340 * Returns the type definition or NULL in case of error
10341 */
10342static xmlSchemaTypePtr
10343xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010344 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010345{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010346 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010347 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010348 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010349 xmlAttrPtr attr;
10350 const xmlChar *attrValue;
10351 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010352 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010353 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010354
Daniel Veillard4255d502002-04-16 15:50:10 +000010355
10356 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10357 return (NULL);
10358
Daniel Veillard01fa6152004-06-29 17:04:39 +000010359 ctxtType = ctxt->ctxtType;
10360
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010361 if (topLevel) {
10362 attr = xmlSchemaGetPropNode(node, "name");
10363 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010364 xmlSchemaPMissingAttrErr(ctxt,
10365 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010366 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010367 } else if (xmlSchemaPValAttrNode(ctxt,
10368 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010369 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10370 return (NULL);
10371 }
10372 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010373
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010374 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010375 /*
10376 * Parse as local complex type definition.
10377 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010378 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010379 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10380 if (type == NULL)
10381 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010382 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010383 type->node = node;
10384 type->type = XML_SCHEMA_TYPE_COMPLEX;
10385 /*
10386 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010387 */
10388 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010389 /*
10390 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010391 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010392 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010393 if (type == NULL)
10394 return (NULL);
10395 type->node = node;
10396 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010397 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010398 }
10399 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010400 /*
10401 * Handle attributes.
10402 */
10403 attr = node->properties;
10404 while (attr != NULL) {
10405 if (attr->ns == NULL) {
10406 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10407 /*
10408 * Attribute "id".
10409 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010410 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10411 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010412 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10413 /*
10414 * Attribute "mixed".
10415 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010416 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010417 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010418 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10419 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010420 /*
10421 * Attributes of global complex type definitions.
10422 */
10423 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10424 /* Pass. */
10425 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10426 /*
10427 * Attribute "abstract".
10428 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010429 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10430 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010431 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10432 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10433 /*
10434 * Attribute "final".
10435 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010436 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010437 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010438 if (xmlSchemaPValAttrBlockFinal(attrValue,
10439 &(type->flags),
10440 -1,
10441 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10442 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10443 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010444 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010445 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010446 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010447 type, (xmlNodePtr) attr, NULL,
10448 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010449 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010450 } else
10451 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010452 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10453 /*
10454 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010455 */
10456 attrValue = xmlSchemaGetNodeContent(ctxt,
10457 (xmlNodePtr) attr);
10458 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010459 -1,
10460 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010461 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010462 -1, -1, -1) != 0) {
10463 xmlSchemaPSimpleTypeErr(ctxt,
10464 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010465 type, (xmlNodePtr) attr, NULL,
10466 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010467 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010468 } else
10469 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010470 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010471 xmlSchemaPIllegalAttrErr(ctxt,
10472 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010473 &des, type, attr);
10474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010475 } else {
10476 xmlSchemaPIllegalAttrErr(ctxt,
10477 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010478 &des, type, attr);
10479 }
10480 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010481 xmlSchemaPIllegalAttrErr(ctxt,
10482 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10483 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010484 }
10485 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010486 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010487 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010488 /*
10489 * Apply default "block" values.
10490 */
10491 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10492 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10493 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10494 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10495 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010496 if (! final) {
10497 /*
10498 * Apply default "block" values.
10499 */
10500 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10501 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10502 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10503 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10504 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010505 /*
10506 * And now for the children...
10507 */
10508 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010509 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010510 child = node->children;
10511 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010512 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10513 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010514 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010515 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010516 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010517 /*
10518 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010519 * Specifying mixed='true' when the <simpleContent>
10520 * alternative is chosen has no effect
10521 */
William M. Bracke7091952004-05-11 15:09:58 +000010522 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10523 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010524 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010525 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010526 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010527 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10528 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010529 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010530 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010531 /*
10532 * SPEC
10533 * "...the third alternative (neither <simpleContent> nor
10534 * <complexContent>) is chosen. This case is understood as shorthand
10535 * for complex content restricting the ·ur-type definition·, and the
10536 * details of the mappings should be modified as necessary.
10537 */
10538 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10539 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010540 /*
10541 * Parse model groups.
10542 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010543 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010544 type->subtypes = (xmlSchemaTypePtr)
10545 xmlSchemaParseModelGroup(ctxt, schema, child,
10546 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010547 child = child->next;
10548 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010549 type->subtypes = (xmlSchemaTypePtr)
10550 xmlSchemaParseModelGroup(ctxt, schema, child,
10551 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010552 child = child->next;
10553 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010554 type->subtypes = (xmlSchemaTypePtr)
10555 xmlSchemaParseModelGroup(ctxt, schema, child,
10556 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010557 child = child->next;
10558 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010559 type->subtypes = (xmlSchemaTypePtr)
10560 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010561 child = child->next;
10562 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010563 /*
10564 * Parse attribute decls/refs.
10565 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010566 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010567 /*
10568 * Parse attribute wildcard.
10569 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010570 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010571 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10572 child = child->next;
10573 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010574 }
10575 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010576 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010577 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010578 &des, type, node, child,
10579 NULL, "(annotation?, (simpleContent | complexContent | "
10580 "((group | all | choice | sequence)?, ((attribute | "
10581 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010582 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010583 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010584 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010585 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010586 return (type);
10587}
10588
Daniel Veillard4255d502002-04-16 15:50:10 +000010589/**
10590 * xmlSchemaParseSchema:
10591 * @ctxt: a schema validation context
10592 * @node: a subtree containing XML Schema informations
10593 *
10594 * parse a XML schema definition from a node set
10595 * *WARNING* this interface is highly subject to change
10596 *
10597 * Returns the internal XML Schema structure built from the resource or
10598 * NULL in case of error
10599 */
10600static xmlSchemaPtr
10601xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10602{
10603 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010604 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010605 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010606 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010607
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010608 /*
10609 * This one is called by xmlSchemaParse only and is used if
10610 * the schema to be parsed was specified via the API; i.e. not
10611 * automatically by the validated instance document.
10612 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010613 if ((ctxt == NULL) || (node == NULL))
10614 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010615 nberrors = ctxt->nberrors;
10616 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010617 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010618 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010619 xmlSchemaImportPtr import;
10620
Daniel Veillard4255d502002-04-16 15:50:10 +000010621 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010622 if (schema == NULL)
10623 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010624 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010625 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010626 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010627 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10628 /*
10629 * TODO: Should we proceed with an invalid target namespace?
10630 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010631 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010632 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10633 /*
10634 * We are parsing the schema for schema!
10635 */
10636 ctxt->isS4S = 1;
10637 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010638 } else {
10639 schema->targetNamespace = NULL;
10640 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010641 /*
10642 * Add the current ns name and location to the import table;
10643 * this is needed to have a consistent mechanism, regardless
10644 * if all schemata are constructed dynamically fired by the
10645 * instance or if the schema to be used was specified via
10646 * the API.
10647 */
10648 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10649 schema->targetNamespace);
10650 if (import == NULL) {
10651 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10652 NULL, NULL, (xmlNodePtr) ctxt->doc,
10653 "Internal error: xmlSchemaParseSchema, "
10654 "failed to add an import entry", NULL);
10655 xmlSchemaFree(schema);
10656 schema = NULL;
10657 return (NULL);
10658 }
10659 import->schemaLocation = ctxt->URL;
10660 /*
10661 * NOTE: We won't set the doc here, otherwise it will be freed
10662 * if the import struct is freed.
10663 * import->doc = ctxt->doc;
10664 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010665 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010666 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10667 } else {
10668 xmlDocPtr doc;
10669
10670 doc = node->doc;
10671
10672 if ((doc != NULL) && (doc->URL != NULL)) {
10673 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10674 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010675 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010676 } else {
10677 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10678 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010679 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010680 }
10681 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010682 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010683 if (ctxt->nberrors != 0) {
10684 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010685 xmlSchemaFree(schema);
10686 schema = NULL;
10687 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010688 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010689 if (schema != NULL)
10690 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010691 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010692#ifdef DEBUG
10693 if (schema == NULL)
10694 xmlGenericError(xmlGenericErrorContext,
10695 "xmlSchemaParse() failed\n");
10696#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010697 return (schema);
10698}
10699
10700/************************************************************************
10701 * *
10702 * Validating using Schemas *
10703 * *
10704 ************************************************************************/
10705
10706/************************************************************************
10707 * *
10708 * Reading/Writing Schemas *
10709 * *
10710 ************************************************************************/
10711
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010712#if 0 /* Will be enabled if it is clear what options are needed. */
10713/**
10714 * xmlSchemaParserCtxtSetOptions:
10715 * @ctxt: a schema parser context
10716 * @options: a combination of xmlSchemaParserOption
10717 *
10718 * Sets the options to be used during the parse.
10719 *
10720 * Returns 0 in case of success, -1 in case of an
10721 * API error.
10722 */
10723static int
10724xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10725 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010726
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010727{
10728 int i;
10729
10730 if (ctxt == NULL)
10731 return (-1);
10732 /*
10733 * WARNING: Change the start value if adding to the
10734 * xmlSchemaParseOption.
10735 */
10736 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10737 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010738 return (-1);
10739 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010740 }
10741 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010742 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010743}
10744
10745/**
10746 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010747 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010748 *
10749 * Returns the option combination of the parser context.
10750 */
10751static int
10752xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010753
10754{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010755 if (ctxt == NULL)
10756 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010757 else
10758 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010759}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010760#endif
10761
Daniel Veillard4255d502002-04-16 15:50:10 +000010762/**
10763 * xmlSchemaNewParserCtxt:
10764 * @URL: the location of the schema
10765 *
10766 * Create an XML Schemas parse context for that file/resource expected
10767 * to contain an XML Schemas file.
10768 *
10769 * Returns the parser context or NULL in case of error
10770 */
10771xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010772xmlSchemaNewParserCtxt(const char *URL)
10773{
Daniel Veillard4255d502002-04-16 15:50:10 +000010774 xmlSchemaParserCtxtPtr ret;
10775
10776 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010777 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010778
10779 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10780 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010781 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010782 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010783 return (NULL);
10784 }
10785 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010786 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010787 ret->dict = xmlDictCreate();
10788 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010789 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010790 return (ret);
10791}
10792
10793/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010794 * xmlSchemaNewMemParserCtxt:
10795 * @buffer: a pointer to a char array containing the schemas
10796 * @size: the size of the array
10797 *
10798 * Create an XML Schemas parse context for that memory buffer expected
10799 * to contain an XML Schemas file.
10800 *
10801 * Returns the parser context or NULL in case of error
10802 */
10803xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010804xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10805{
Daniel Veillard6045c902002-10-09 21:13:59 +000010806 xmlSchemaParserCtxtPtr ret;
10807
10808 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010809 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010810
10811 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10812 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010813 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010814 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010815 return (NULL);
10816 }
10817 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10818 ret->buffer = buffer;
10819 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010820 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010821 return (ret);
10822}
10823
10824/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010825 * xmlSchemaNewDocParserCtxt:
10826 * @doc: a preparsed document tree
10827 *
10828 * Create an XML Schemas parse context for that document.
10829 * NB. The document may be modified during the parsing process.
10830 *
10831 * Returns the parser context or NULL in case of error
10832 */
10833xmlSchemaParserCtxtPtr
10834xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10835{
10836 xmlSchemaParserCtxtPtr ret;
10837
10838 if (doc == NULL)
10839 return (NULL);
10840
10841 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10842 if (ret == NULL) {
10843 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10844 NULL);
10845 return (NULL);
10846 }
10847 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10848 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010849 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010850 /* The application has responsibility for the document */
10851 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010852
10853 return (ret);
10854}
10855
10856/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010857 * xmlSchemaFreeParserCtxt:
10858 * @ctxt: the schema parser context
10859 *
10860 * Free the resources associated to the schema parser context
10861 */
10862void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010863xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10864{
Daniel Veillard4255d502002-04-16 15:50:10 +000010865 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010866 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010867 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010868 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010869 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010870 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010871 xmlFree(ctxt->assemble);
10872 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010873 if (ctxt->vctxt != NULL) {
10874 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10875 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010876 if (ctxt->localImports != NULL)
10877 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010878 if (ctxt->substGroups != NULL)
10879 xmlHashFree(ctxt->substGroups,
10880 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010881 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010882 xmlFree(ctxt);
10883}
10884
10885/************************************************************************
10886 * *
10887 * Building the content models *
10888 * *
10889 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010890
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010891static void
10892xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000010893 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010894{
Daniel Veillarda980bef2005-07-18 21:34:03 +000010895 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010896 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010897 xmlSchemaSubstGroupPtr substGroup;
10898 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010899
10900 elemDecl = (xmlSchemaElementPtr) particle->children;
10901 /*
10902 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010903 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010904 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000010905 if (end == NULL)
10906 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010907 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10908 if (substGroup == NULL) {
10909 xmlSchemaPErr(pctxt, GET_NODE(particle),
10910 XML_SCHEMAP_INTERNAL,
10911 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10912 "declaration is marked having a subst. group but none "
10913 "available.\n", elemDecl->name, NULL);
10914 return;
10915 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000010916 if (counter >= 0) {
10917 /*
10918 * NOTE that we put the declaration in, even if it's abstract,
10919 */
10920 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
10921 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10922 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10923 /*
10924 * Add subst. group members.
10925 */
10926 for (i = 0; i < substGroup->members->nbItems; i++) {
10927 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10928 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10929 member->name, member->targetNamespace, member);
10930 }
10931 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010932 /*
10933 * NOTE that we put the declaration in, even if it's abstract,
10934 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010935 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010936 xmlAutomataNewTransition2(pctxt->am,
10937 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010938 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10939 /*
10940 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010941 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010942 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010943 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000010944 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
10945 member->name, member->targetNamespace,
10946 1, 1, member);
10947 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010948 }
10949 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010950 xmlAutomataStatePtr hop;
10951 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10952 UNBOUNDED : particle->maxOccurs - 1;
10953 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10954
10955 counter =
10956 xmlAutomataNewCounter(pctxt->am, minOccurs,
10957 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010958 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010959
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010960 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010961 xmlAutomataNewTransition2(pctxt->am,
10962 start, NULL,
10963 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010964 hop);
10965 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000010966 * Add subst. group members.
10967 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010968 for (i = 0; i < substGroup->members->nbItems; i++) {
10969 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10970 xmlAutomataNewEpsilon(pctxt->am,
10971 xmlAutomataNewTransition2(pctxt->am,
10972 start, NULL,
10973 member->name, member->targetNamespace, member),
10974 hop);
10975 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010976 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10977 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10978 }
10979 if (particle->minOccurs == 0)
10980 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010981 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010982}
10983
10984static void
10985xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10986 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010987{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010988 if (((xmlSchemaElementPtr) particle->children)->flags &
10989 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010990 /*
10991 * Substitution groups.
10992 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000010993 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010994 } else {
10995 xmlSchemaElementPtr elemDecl;
10996 xmlAutomataStatePtr start;
10997
10998 elemDecl = (xmlSchemaElementPtr) particle->children;
10999
11000 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011001 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011002 if (particle->maxOccurs == 1) {
11003 start = ctxt->state;
11004 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011005 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11006 } else if ((particle->maxOccurs >= UNBOUNDED) &&
11007 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011008 /* Special case. */
11009 start = ctxt->state;
11010 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11011 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011012 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011013 } else {
11014 int counter;
11015 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11016 UNBOUNDED : particle->maxOccurs - 1;
11017 int minOccurs = particle->minOccurs < 1 ?
11018 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011019
11020 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011021 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11022 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11023 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11024 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11025 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11026 NULL, counter);
11027 }
11028 if (particle->minOccurs == 0)
11029 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11030 }
11031}
11032
Daniel Veillard4255d502002-04-16 15:50:10 +000011033/**
11034 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011035 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011036 * @particle: the particle component
11037 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011038 *
11039 * Generate the automata sequence needed for that type
11040 */
11041static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011042xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011043 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011044 const xmlChar * name)
11045{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011046 if (particle == NULL) {
11047 xmlSchemaPErr(ctxt, NULL,
11048 XML_SCHEMAP_INTERNAL,
11049 "Internal error: xmlSchemaBuildAContentModel, "
11050 "particle is NULL.\n", NULL, NULL);
11051 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011052 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011053 if (particle->children == NULL) {
11054 xmlSchemaPErr(ctxt, GET_NODE(particle),
11055 XML_SCHEMAP_INTERNAL,
11056 "Internal error: xmlSchemaBuildAContentModel, "
11057 "no term on particle.\n", NULL, NULL);
11058 return;
11059 }
11060
11061 switch (particle->children->type) {
11062 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011063 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011064 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011065 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011066
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011067 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011068
Daniel Veillardc0826a72004-08-10 14:17:33 +000011069 start = ctxt->state;
11070 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011071
11072 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011073 if (wild->any == 1) {
11074 /*
11075 * We need to add both transitions:
11076 *
11077 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011078 */
11079 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011080 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011081 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011082 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11083 /*
11084 * 2. the {"*"} for elements in no namespace.
11085 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011086 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011087 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011088 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011089 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11090
11091 } else if (wild->nsSet != NULL) {
11092 ns = wild->nsSet;
11093 do {
11094 ctxt->state = start;
11095 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011096 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011097 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11098 ns = ns->next;
11099 } while (ns != NULL);
11100
11101 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011102
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011103 /*
11104 * Lead nodes with the negated namespace to the sink-state
11105 * {"*", "##other"}.
11106 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011107 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011108 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011109 /*
11110 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011111 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011112 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011113 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011114 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011115 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011116 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011117 } else {
11118 int counter;
11119 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011120 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011121 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011122 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011123 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011124
Daniel Veillardc0826a72004-08-10 14:17:33 +000011125 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011126 hop = xmlAutomataNewState(ctxt->am);
11127 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011128 ctxt->state =
11129 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011130 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011131 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011132 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011133 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011134 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011135 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011136 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011137 ns = wild->nsSet;
11138 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011139 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011140 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011141 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011142 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11143 ns = ns->next;
11144 } while (ns != NULL);
11145
11146 } else if (wild->negNsSet != NULL) {
Daniel Veillard9efc4762005-07-19 14:33:55 +000011147 ctxt->state = xmlAutomataNewNegTrans(ctxt->am,
11148 start, hop, BAD_CAST "*", wild->negNsSet->value,
11149 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011150 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011151 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11152 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11153 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011154 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011155 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011156 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011157 ctxt->state = end;
11158 break;
11159 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011160 case XML_SCHEMA_TYPE_ELEMENT:
11161 xmlSchemaBuildContentModelForElement(ctxt, particle);
11162 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011163 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011164 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011165
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011166 /*
11167 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011168 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011169 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011170 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11171 sub = particle->children->children;
11172 while (sub != NULL) {
11173 xmlSchemaBuildAContentModel(ctxt,
11174 (xmlSchemaParticlePtr) sub, name);
11175 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011176 }
11177 } else {
11178 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011179
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011180 if (particle->maxOccurs >= UNBOUNDED) {
11181 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011182 xmlAutomataStatePtr tmp;
11183 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011184
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011185 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011186 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011187 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011188
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011189 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011190 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011191
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011192 sub = particle->children->children;
11193 while (sub != NULL) {
11194 xmlSchemaBuildAContentModel(ctxt,
11195 (xmlSchemaParticlePtr) sub, name);
11196 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011197 }
11198 tmp = ctxt->state;
11199 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11200 oldstate, counter);
11201 ctxt->state =
11202 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11203 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011204
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011205 } else {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011206 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11207 oldstate, NULL);
11208 oldstate = ctxt->state;
11209
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011210 sub = particle->children->children;
11211 while (sub != NULL) {
11212 xmlSchemaBuildAContentModel(ctxt,
11213 (xmlSchemaParticlePtr) sub, name);
11214 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011215 }
11216 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11217 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011218 /*
11219 * epsilon needed to block previous trans from
11220 * being allowed to enter back from another
11221 * construct
11222 */
11223 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11224 ctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011225 if (particle->minOccurs == 0) {
11226 xmlAutomataNewEpsilon(ctxt->am,
11227 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011228 }
11229 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011230 } else if ((particle->maxOccurs > 1)
11231 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011232 xmlAutomataStatePtr tmp;
11233 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011234
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011235 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011236 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011237 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011238
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011239 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011240 particle->minOccurs - 1,
11241 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011242
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011243 sub = particle->children->children;
11244 while (sub != NULL) {
11245 xmlSchemaBuildAContentModel(ctxt,
11246 (xmlSchemaParticlePtr) sub, name);
11247 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011248 }
11249 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011250 xmlAutomataNewCountedTrans(ctxt->am,
11251 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011252 ctxt->state =
11253 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11254 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011255 if (particle->minOccurs == 0) {
11256 xmlAutomataNewEpsilon(ctxt->am,
11257 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011258 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011259 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011260 sub = particle->children->children;
11261 while (sub != NULL) {
11262 xmlSchemaBuildAContentModel(ctxt,
11263 (xmlSchemaParticlePtr) sub, name);
11264 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011265 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011266 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011267 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11268 ctxt->state);
11269 }
11270 }
11271 }
11272 break;
11273 }
11274 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011275 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011276 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011277
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011278 start = ctxt->state;
11279 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011280
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011281 /*
11282 * iterate over the subtypes and remerge the end with an
11283 * epsilon transition
11284 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011285 if (particle->maxOccurs == 1) {
11286 sub = particle->children->children;
11287 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011288 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011289 xmlSchemaBuildAContentModel(ctxt,
11290 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011291 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011292 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011293 }
11294 } else {
11295 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011296 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011297 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11298 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011299 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011300 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011301
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011302 /*
11303 * use a counter to keep track of the number of transtions
11304 * which went through the choice.
11305 */
11306 counter =
Daniel Veillardafc05b62005-07-17 06:11:19 +000011307 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011308 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011309 base = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011310
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011311 sub = particle->children->children;
11312 while (sub != NULL) {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011313 ctxt->state = base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011314 xmlSchemaBuildAContentModel(ctxt,
11315 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011316 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011317 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011318 }
Daniel Veillardafc05b62005-07-17 06:11:19 +000011319 xmlAutomataNewEpsilon(ctxt->am, start, base);
11320 xmlAutomataNewCountedTrans(ctxt->am, hop, base, counter);
11321 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011322 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011323 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011324 xmlAutomataNewEpsilon(ctxt->am, start, end);
11325 }
11326 ctxt->state = end;
11327 break;
11328 }
11329 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000011330 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011331 xmlSchemaParticlePtr sub;
11332 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011333 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011334
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011335 sub = (xmlSchemaParticlePtr) particle->children->children;
11336 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011337 break;
11338 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011339 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011340 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011341
11342 elemDecl = (xmlSchemaElementPtr) sub->children;
11343 if (elemDecl == NULL) {
11344 xmlSchemaPErr(ctxt, NULL,
11345 XML_SCHEMAP_INTERNAL,
11346 "Internal error: xmlSchemaBuildAContentModel, "
11347 "<element> particle a NULL term.\n", NULL, NULL);
11348 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011349 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011350 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011351 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011352 * {particles} of the group must be 0 or 1; this is
11353 * already ensured during the parse of the content of
11354 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011355 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011356 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11357 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011358
Daniel Veillarda980bef2005-07-18 21:34:03 +000011359 /*
11360 * This is an abstract group, we need to share
11361 * the same counter for all the element transitions
11362 * derived from the group
11363 */
11364 counter = xmlAutomataNewCounter(ctxt->am,
11365 sub->minOccurs, sub->maxOccurs);
11366 xmlSchemaBuildContentModelForSubstGroup(ctxt,
11367 sub, counter, ctxt->state);
11368 } else {
11369 if ((sub->minOccurs == 1) &&
11370 (sub->maxOccurs == 1)) {
11371 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11372 ctxt->state,
11373 elemDecl->name,
11374 elemDecl->targetNamespace,
11375 1, 1, elemDecl);
11376 } else if ((sub->minOccurs == 0) &&
11377 (sub->maxOccurs == 1)) {
11378
11379 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11380 ctxt->state,
11381 elemDecl->name,
11382 elemDecl->targetNamespace,
11383 0,
11384 1,
11385 elemDecl);
11386 }
11387 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011388 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011389 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011390 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011391 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011392 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011393 break;
11394 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011395 default:
11396 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011397 "Internal error: xmlSchemaBuildAContentModel, found "
11398 "unexpected term of type %d in content model of complex "
11399 "type '%s'.\n",
11400 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011401 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011402 }
11403}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011404
Daniel Veillard4255d502002-04-16 15:50:10 +000011405/**
11406 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011407 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011408 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011409 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011410 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011411 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011412 */
11413static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011414xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011415 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011416 const xmlChar * name)
11417{
Daniel Veillard4255d502002-04-16 15:50:10 +000011418 xmlAutomataStatePtr start;
11419
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011420 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11421 (type->contModel != NULL) ||
11422 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11423 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011424 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011425
11426#ifdef DEBUG_CONTENT
11427 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011428 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011429#endif
11430
Daniel Veillard4255d502002-04-16 15:50:10 +000011431 ctxt->am = xmlNewAutomata();
11432 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011433 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011434 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011435 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011436 }
11437 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011438 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011439 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011440 type->contModel = xmlAutomataCompile(ctxt->am);
11441 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011442 xmlSchemaPCustomErr(ctxt,
11443 XML_SCHEMAP_INTERNAL,
11444 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011445 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011446 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011447 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011448 XML_SCHEMAP_NOT_DETERMINISTIC,
11449 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011450 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011451 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011452 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011453#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011454 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011455 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011456 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011457#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011458 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011459 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011460 xmlFreeAutomata(ctxt->am);
11461 ctxt->am = NULL;
11462}
11463
11464/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011465 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011466 * @elem: the schema element context
11467 * @ctxt: the schema parser context
11468 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011469 * Resolves the references of an element declaration
11470 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011471 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011472 */
11473static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011474xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011475 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011476 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011477 const xmlChar * context ATTRIBUTE_UNUSED,
11478 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011479{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011480 if ((ctxt == NULL) || (elemDecl == NULL) ||
11481 ((elemDecl != NULL) &&
11482 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011483 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011484 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011485
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011486 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011487 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011488
11489 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011490 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011491 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011492 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011493 elemDecl->namedTypeNs);
11494 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011495 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011496 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011497 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011498 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011499 XML_SCHEMA_TYPE_BASIC, "type definition");
11500 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011501 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011502 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011503 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011504 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011505
Daniel Veillardc0826a72004-08-10 14:17:33 +000011506 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011507 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011508 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011509 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011510 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11511 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011512 if (substHead == NULL) {
11513 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011514 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011515 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011516 "substitutionGroup", elemDecl->substGroup,
11517 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011518 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011519 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011520 /*
11521 * Set the "substitution group affiliation".
11522 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011523 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011524 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011525 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011526 * (type definition)...otherwise the {type definition} of the
11527 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011528 * the substitutionGroup [attribute], if present
11529 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011530 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011531 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011532 }
11533 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011534 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11535 (elemDecl->substGroup == NULL))
11536 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011537}
11538
11539/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011540 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011541 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011542 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011543 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011544 * Checks and builds the "member type definitions" property of the union
11545 * simple type. This handles part (1), part (2) is done in
11546 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11547 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011548 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011549 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011550static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011551xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11552 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011553{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011554
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011555 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011556 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011557
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011558 /*
11559 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11560 * define the explicit members as the type definitions ·resolved·
11561 * to by the items in the ·actual value· of the memberTypes [attribute],
11562 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011563 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011564 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011565 /*
11566 * Resolve references.
11567 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011568 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011569 lastLink = NULL;
11570 while (link != NULL) {
11571 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011572
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011573 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11574 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11575
11576 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11577 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11578 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011579 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011580 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11581 /*
11582 * Remove the member type link.
11583 */
11584 if (lastLink == NULL)
11585 type->memberTypes = link->next;
11586 else
11587 lastLink->next = link->next;
11588 newLink = link;
11589 link = link->next;
11590 xmlFree(newLink);
11591 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011592 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011593 lastLink = link;
11594 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011595 }
11596 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011597 /*
11598 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011599 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011600 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011601 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011602 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11603 if (link == NULL) {
11604 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11605 return (-1);
11606 }
11607 link->type = memberType;
11608 link->next = NULL;
11609 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011610 type->memberTypes = link;
11611 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011612 lastLink->next = link;
11613 lastLink = link;
11614 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011615 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011616 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011617}
11618
Daniel Veillard4255d502002-04-16 15:50:10 +000011619/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011620 * xmlSchemaIsDerivedFromBuiltInType:
11621 * @ctxt: the schema parser context
11622 * @type: the type definition
11623 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011624 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011625 *
11626 * Returns 1 if the type has the given value type, or
11627 * is derived from such a type.
11628 */
William M. Brack803812b2004-06-03 02:11:24 +000011629static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011630xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011631{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011632 if (type == NULL)
11633 return (0);
11634 if (IS_COMPLEX_TYPE(type))
11635 return (0);
11636 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11637 if (type->builtInType == valType)
11638 return(1);
11639 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11640 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11641 return (0);
11642 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11643 } else
11644 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011645
11646 return (0);
11647}
11648
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011649#if 0
11650/**
11651 * xmlSchemaIsDerivedFromBuiltInType:
11652 * @ctxt: the schema parser context
11653 * @type: the type definition
11654 * @valType: the value type
11655 *
11656 *
11657 * Returns 1 if the type has the given value type, or
11658 * is derived from such a type.
11659 */
11660static int
11661xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11662{
11663 if (type == NULL)
11664 return (0);
11665 if (IS_COMPLEX_TYPE(type))
11666 return (0);
11667 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11668 if (type->builtInType == valType)
11669 return(1);
11670 return (0);
11671 } else
11672 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11673
11674 return (0);
11675}
11676#endif
11677
11678static xmlSchemaTypePtr
11679xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11680{
11681 if (type == NULL)
11682 return (NULL);
11683 if (IS_COMPLEX_TYPE(type))
11684 return (NULL);
11685 if (type->type == XML_SCHEMA_TYPE_BASIC)
11686 return(type);
11687 else
11688 return(xmlSchemaQueryBuiltInType(type->subtypes));
11689
11690 return (NULL);
11691}
11692
Daniel Veillard3646d642004-06-02 19:19:14 +000011693/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011694 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011695 * @type: the simpleType definition
11696 *
11697 * Returns the primitive type of the given type or
11698 * NULL in case of error.
11699 */
11700static xmlSchemaTypePtr
11701xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11702{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011703
Daniel Veillard01fa6152004-06-29 17:04:39 +000011704 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011705 /*
11706 * Note that anySimpleType is actually not a primitive type
11707 * but we need that here.
11708 */
11709 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11710 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011711 return (type);
11712 type = type->baseType;
11713 }
11714
11715 return (NULL);
11716}
11717
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011718#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011719/**
11720 * xmlSchemaGetBuiltInTypeAncestor:
11721 * @type: the simpleType definition
11722 *
11723 * Returns the primitive type of the given type or
11724 * NULL in case of error.
11725 */
11726static xmlSchemaTypePtr
11727xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11728{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011729 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011730 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011731 while (type != NULL) {
11732 if (type->type == XML_SCHEMA_TYPE_BASIC)
11733 return (type);
11734 type = type->baseType;
11735 }
11736
11737 return (NULL);
11738}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011739#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011740
Daniel Veillard01fa6152004-06-29 17:04:39 +000011741/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011742 * xmlSchemaBuildAttributeUsesOwned:
11743 * @ctxt: the schema parser context
11744 * @type: the complex type definition
11745 * @cur: the attribute declaration list
11746 * @lastUse: the top of the attribute use list
11747 *
11748 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011749 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011750 * xmlSchemaBuildAttributeValidation only.
11751 */
11752static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011753xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011754 xmlSchemaAttributePtr cur,
11755 xmlSchemaAttributeLinkPtr *uses,
11756 xmlSchemaAttributeLinkPtr *lastUse)
11757{
11758 xmlSchemaAttributeLinkPtr tmp;
11759 while (cur != NULL) {
11760 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011761 /*
11762 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11763 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011764 * <attributeGroup> [children], if any."
11765 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011766 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11767 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011768 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011769 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011770 }
11771 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011772 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011773 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011774 */
11775 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011776 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11777 if (tmp == NULL) {
11778 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11779 return (-1);
11780 }
11781 tmp->attr = cur;
11782 tmp->next = NULL;
11783 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011784 *uses = tmp;
11785 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011786 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011787 *lastUse = tmp;
11788 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011789 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011790 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011791 return (0);
11792}
11793
Daniel Veillard50355f02004-06-08 17:52:16 +000011794/**
11795 * xmlSchemaCloneWildcardNsConstraints:
11796 * @ctxt: the schema parser context
11797 * @dest: the destination wildcard
11798 * @source: the source wildcard
11799 *
11800 * Clones the namespace constraints of source
11801 * and assignes them to dest.
11802 * Returns -1 on internal error, 0 otherwise.
11803 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011804static int
11805xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11806 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011807 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011808{
11809 xmlSchemaWildcardNsPtr cur, tmp, last;
11810
11811 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011812 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011813 (*dest)->any = source->any;
11814 cur = source->nsSet;
11815 last = NULL;
11816 while (cur != NULL) {
11817 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11818 if (tmp == NULL)
11819 return(-1);
11820 tmp->value = cur->value;
11821 if (last == NULL)
11822 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011823 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011824 last->next = tmp;
11825 last = tmp;
11826 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011827 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011828 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011829 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011830 if (source->negNsSet != NULL) {
11831 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11832 if ((*dest)->negNsSet == NULL)
11833 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011834 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011835 } else
11836 (*dest)->negNsSet = NULL;
11837 return(0);
11838}
11839
Daniel Veillard50355f02004-06-08 17:52:16 +000011840/**
11841 * xmlSchemaUnionWildcards:
11842 * @ctxt: the schema parser context
11843 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011844 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011845 *
11846 * Unions the namespace constraints of the given wildcards.
11847 * @completeWild will hold the resulting union.
11848 * Returns a positive error code on failure, -1 in case of an
11849 * internal error, 0 otherwise.
11850 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011851static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011852xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011853 xmlSchemaWildcardPtr completeWild,
11854 xmlSchemaWildcardPtr curWild)
11855{
11856 xmlSchemaWildcardNsPtr cur, curB, tmp;
11857
11858 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011859 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011860 * value.
11861 */
11862 if ((completeWild->any == curWild->any) &&
11863 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11864 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011865
Daniel Veillard3646d642004-06-02 19:19:14 +000011866 if ((completeWild->negNsSet == NULL) ||
11867 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011868
Daniel Veillard3646d642004-06-02 19:19:14 +000011869 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011870 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011871
11872 /*
11873 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011874 */
11875 cur = completeWild->nsSet;
11876 while (cur != NULL) {
11877 found = 0;
11878 curB = curWild->nsSet;
11879 while (curB != NULL) {
11880 if (cur->value == curB->value) {
11881 found = 1;
11882 break;
11883 }
11884 curB = curB->next;
11885 }
11886 if (!found)
11887 break;
11888 cur = cur->next;
11889 }
11890 if (found)
11891 return(0);
11892 } else
11893 return(0);
11894 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011895 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011896 /*
11897 * 2 If either O1 or O2 is any, then any must be the value
11898 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011899 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011900 if (completeWild->any == 0) {
11901 completeWild->any = 1;
11902 if (completeWild->nsSet != NULL) {
11903 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11904 completeWild->nsSet = NULL;
11905 }
11906 if (completeWild->negNsSet != NULL) {
11907 xmlFree(completeWild->negNsSet);
11908 completeWild->negNsSet = NULL;
11909 }
11910 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011911 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011912 }
11913 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011914 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011915 * then the union of those sets must be the value.
11916 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011917 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011918 int found;
11919 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011920
Daniel Veillard3646d642004-06-02 19:19:14 +000011921 cur = curWild->nsSet;
11922 start = completeWild->nsSet;
11923 while (cur != NULL) {
11924 found = 0;
11925 curB = start;
11926 while (curB != NULL) {
11927 if (cur->value == curB->value) {
11928 found = 1;
11929 break;
11930 }
11931 curB = curB->next;
11932 }
11933 if (!found) {
11934 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011935 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011936 return (-1);
11937 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011938 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011939 completeWild->nsSet = tmp;
11940 }
11941 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011942 }
11943
Daniel Veillard3646d642004-06-02 19:19:14 +000011944 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011945 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011946 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011947 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011948 * or ·absent·), then a pair of not and ·absent· must be the value.
11949 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011950 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011951 (curWild->negNsSet != NULL) &&
11952 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
11953 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000011954
11955 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011956 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011957 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011958 * 5.
11959 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011960 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011961 (completeWild->negNsSet->value != NULL) &&
11962 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011963 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011964 (curWild->negNsSet->value != NULL) &&
11965 (completeWild->nsSet != NULL))) {
11966
11967 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011968
Daniel Veillard3646d642004-06-02 19:19:14 +000011969 if (completeWild->nsSet != NULL) {
11970 cur = completeWild->nsSet;
11971 curB = curWild->negNsSet;
11972 } else {
11973 cur = curWild->nsSet;
11974 curB = completeWild->negNsSet;
11975 }
11976 nsFound = 0;
11977 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011978 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011979 absentFound = 1;
11980 else if (cur->value == curB->value)
11981 nsFound = 1;
11982 if (nsFound && absentFound)
11983 break;
11984 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011985 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011986
11987 if (nsFound && absentFound) {
11988 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011989 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000011990 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011991 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011992 completeWild->any = 1;
11993 if (completeWild->nsSet != NULL) {
11994 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11995 completeWild->nsSet = NULL;
11996 }
11997 if (completeWild->negNsSet != NULL) {
11998 xmlFree(completeWild->negNsSet);
11999 completeWild->negNsSet = NULL;
12000 }
12001 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012002 /*
12003 * 5.2 If the set S includes the negated namespace name
12004 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000012005 * be the value.
12006 */
12007 if (completeWild->nsSet != NULL) {
12008 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12009 completeWild->nsSet = NULL;
12010 }
12011 if (completeWild->negNsSet == NULL) {
12012 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12013 if (completeWild->negNsSet == NULL)
12014 return (-1);
12015 }
12016 completeWild->negNsSet->value = NULL;
12017 } else if ((!nsFound) && absentFound) {
12018 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012019 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012020 * namespace name, then the union is not expressible.
12021 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012022 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012023 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012024 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012025 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012026 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012027 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012028 /*
12029 * 5.4 If the set S does not include either the negated namespace
12030 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012031 * and a namespace name must be the value.
12032 */
12033 if (completeWild->negNsSet == NULL) {
12034 if (completeWild->nsSet != NULL) {
12035 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12036 completeWild->nsSet = NULL;
12037 }
12038 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12039 if (completeWild->negNsSet == NULL)
12040 return (-1);
12041 completeWild->negNsSet->value = curWild->negNsSet->value;
12042 }
12043 }
12044 return (0);
12045 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012046 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012047 * 6.
12048 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012049 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012050 (completeWild->negNsSet->value == NULL) &&
12051 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012052 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012053 (curWild->negNsSet->value == NULL) &&
12054 (completeWild->nsSet != NULL))) {
12055
12056 if (completeWild->nsSet != NULL) {
12057 cur = completeWild->nsSet;
12058 } else {
12059 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012060 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012061 while (cur != NULL) {
12062 if (cur->value == NULL) {
12063 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012064 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012065 * value.
12066 */
12067 completeWild->any = 1;
12068 if (completeWild->nsSet != NULL) {
12069 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12070 completeWild->nsSet = NULL;
12071 }
12072 if (completeWild->negNsSet != NULL) {
12073 xmlFree(completeWild->negNsSet);
12074 completeWild->negNsSet = NULL;
12075 }
12076 return (0);
12077 }
12078 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012079 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012080 if (completeWild->negNsSet == NULL) {
12081 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012082 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012083 * and ·absent· must be the value.
12084 */
12085 if (completeWild->nsSet != NULL) {
12086 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12087 completeWild->nsSet = NULL;
12088 }
12089 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12090 if (completeWild->negNsSet == NULL)
12091 return (-1);
12092 completeWild->negNsSet->value = NULL;
12093 }
12094 return (0);
12095 }
12096 return (0);
12097
12098}
12099
Daniel Veillard50355f02004-06-08 17:52:16 +000012100/**
12101 * xmlSchemaIntersectWildcards:
12102 * @ctxt: the schema parser context
12103 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012104 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012105 *
12106 * Intersects the namespace constraints of the given wildcards.
12107 * @completeWild will hold the resulting intersection.
12108 * Returns a positive error code on failure, -1 in case of an
12109 * internal error, 0 otherwise.
12110 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012111static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012112xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012113 xmlSchemaWildcardPtr completeWild,
12114 xmlSchemaWildcardPtr curWild)
12115{
William M. Brack803812b2004-06-03 02:11:24 +000012116 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012117
12118 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012119 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012120 * value.
12121 */
12122 if ((completeWild->any == curWild->any) &&
12123 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12124 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012125
Daniel Veillard3646d642004-06-02 19:19:14 +000012126 if ((completeWild->negNsSet == NULL) ||
12127 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012128
Daniel Veillard3646d642004-06-02 19:19:14 +000012129 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012130 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012131
12132 /*
12133 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012134 */
12135 cur = completeWild->nsSet;
12136 while (cur != NULL) {
12137 found = 0;
12138 curB = curWild->nsSet;
12139 while (curB != NULL) {
12140 if (cur->value == curB->value) {
12141 found = 1;
12142 break;
12143 }
12144 curB = curB->next;
12145 }
12146 if (!found)
12147 break;
12148 cur = cur->next;
12149 }
12150 if (found)
12151 return(0);
12152 } else
12153 return(0);
12154 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012155 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012156 /*
12157 * 2 If either O1 or O2 is any, then the other must be the value.
12158 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012160 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012161 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012162 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012163 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012164 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012165 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12166 * name or ·absent·) and the other is a set of (namespace names or
12167 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012168 * the set, minus ·absent· if it was in the set, must be the value.
12169 */
12170 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12171 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12172 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012173
Daniel Veillard3646d642004-06-02 19:19:14 +000012174 if (completeWild->nsSet == NULL) {
12175 neg = completeWild->negNsSet->value;
12176 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12177 return(-1);
12178 } else
12179 neg = curWild->negNsSet->value;
12180 /*
12181 * Remove absent and negated.
12182 */
12183 prev = NULL;
12184 cur = completeWild->nsSet;
12185 while (cur != NULL) {
12186 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012187 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012188 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012189 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012190 prev->next = cur->next;
12191 xmlFree(cur);
12192 break;
12193 }
12194 prev = cur;
12195 cur = cur->next;
12196 }
12197 if (neg != NULL) {
12198 prev = NULL;
12199 cur = completeWild->nsSet;
12200 while (cur != NULL) {
12201 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012202 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012203 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012204 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012205 prev->next = cur->next;
12206 xmlFree(cur);
12207 break;
12208 }
12209 prev = cur;
12210 cur = cur->next;
12211 }
12212 }
12213
12214 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012215 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012216 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012217 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012218 * then the intersection of those sets must be the value.
12219 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012220 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012221 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012222
Daniel Veillard3646d642004-06-02 19:19:14 +000012223 cur = completeWild->nsSet;
12224 prev = NULL;
12225 while (cur != NULL) {
12226 found = 0;
12227 curB = curWild->nsSet;
12228 while (curB != NULL) {
12229 if (cur->value == curB->value) {
12230 found = 1;
12231 break;
12232 }
12233 curB = curB->next;
12234 }
12235 if (!found) {
12236 if (prev == NULL)
12237 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012238 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012239 prev->next = cur->next;
12240 tmp = cur->next;
12241 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012242 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012243 continue;
12244 }
12245 prev = cur;
12246 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012247 }
12248
Daniel Veillard3646d642004-06-02 19:19:14 +000012249 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012250 }
12251 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012252 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012253 */
12254 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012255 (curWild->negNsSet != NULL) &&
12256 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012257 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012258 (curWild->negNsSet->value != NULL)) {
12259
12260 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012261 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012262 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012263 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012264 }
12265 /*
12266 * 6 If the one is a negation of a namespace name and the other
12267 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012268 * of a namespace name must be the value.
12269 */
12270 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12271 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012272 (completeWild->negNsSet->value == NULL)) {
12273 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012274 }
12275 return(0);
12276}
12277
Daniel Veillard50355f02004-06-08 17:52:16 +000012278/**
12279 * xmlSchemaIsWildcardNsConstraintSubset:
12280 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012281 * @sub: the first wildcard
12282 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012283 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012284 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12285 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012286 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012287 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012288 */
12289static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012290xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12291 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012292{
Daniel Veillard50355f02004-06-08 17:52:16 +000012293 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012294 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012295 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012296 if (super->any)
12297 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012298 /*
12299 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12300 * 2.2 super must be a pair of not and the same value.
12301 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012302 if ((sub->negNsSet != NULL) &&
12303 (super->negNsSet != NULL) &&
12304 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012305 return (0);
12306 /*
12307 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012308 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012309 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012310 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012311 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012312 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012313 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012314 xmlSchemaWildcardNsPtr cur, curB;
12315 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012316
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012317 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012318 while (cur != NULL) {
12319 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012320 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012321 while (curB != NULL) {
12322 if (cur->value == curB->value) {
12323 found = 1;
12324 break;
12325 }
12326 curB = curB->next;
12327 }
12328 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012329 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012330 cur = cur->next;
12331 }
12332 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012333 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012334 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012335 xmlSchemaWildcardNsPtr cur;
12336 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012337 * 3.2.2 super must be a pair of not and a namespace name or
12338 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012339 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012340 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012341 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012342 if (cur->value == super->negNsSet->value)
12343 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012344 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012345 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012346 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012347 }
12348 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012349 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012350}
12351
12352/**
12353 * xmlSchemaBuildCompleteAttributeWildcard:
12354 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012355 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012356 * @completeWild: the resulting complete wildcard
12357 *
12358 * Returns -1 in case of an internal error, 0 otherwise.
12359 */
12360static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012361xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012362 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012363 xmlSchemaWildcardPtr *completeWild)
12364{
Daniel Veillard3646d642004-06-02 19:19:14 +000012365 while (attrs != NULL) {
12366 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12367 xmlSchemaAttributeGroupPtr group;
12368
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012369 group = (xmlSchemaAttributeGroupPtr) attrs;
12370 /*
12371 * Handle attribute group references.
12372 */
12373 if (group->ref != NULL) {
12374 if (group->refItem == NULL) {
12375 /*
12376 * TODO: Should we raise a warning here?
12377 */
12378 /*
12379 * The referenced attribute group definition could not
12380 * be resolved beforehand, so skip.
12381 */
12382 attrs = attrs->next;
12383 continue;
12384 } else
12385 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012386 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012387 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012388 * For every attribute group definition, an intersected wildcard
12389 * will be created (assumed that a wildcard exists on the
12390 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012391 * at all).
12392 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12393 * that the intersection will be performed only once.
12394 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012395 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12396 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012397 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012398 group->attributes, &group->attributeWildcard) == -1)
12399 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012400 }
12401 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012402 }
12403 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012404 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012405 /*
12406 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012407 *
12408 * Although the complete wildcard might not correspond to any
12409 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012410 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012411 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12412 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12413 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012414 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012415 completeWild, group->attributeWildcard) == -1)
12416 return (-1);
12417 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012418 (*completeWild)->node = group->attributeWildcard->node;
12419 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012420 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012421 }
12422 }
12423 attrs = attrs->next;
12424 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012425
12426 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012427}
12428
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012429static int
12430xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12431 int *fixed,
12432 const xmlChar **value,
12433 xmlSchemaValPtr *val)
12434{
12435 *fixed = 0;
12436 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012437 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012438 *val = NULL;
12439
12440 if (item->defValue == NULL)
12441 item = item->refDecl;
12442
12443 if (item == NULL)
12444 return (0);
12445
12446 if (item->defValue != NULL) {
12447 *value = item->defValue;
12448 if (val != 0)
12449 *val = item->defVal;
12450 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12451 *fixed = 1;
12452 return (1);
12453 }
12454 return (0);
12455}
Daniel Veillard3646d642004-06-02 19:19:14 +000012456/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012457 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012458 * @wild: the wildcard
12459 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012460 *
12461 * Validation Rule: Wildcard allows Namespace Name
12462 * (cvc-wildcard-namespace)
12463 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012464 *
12465 * Returns 1 if the given namespace matches the wildcard,
12466 * 0 otherwise.
12467 */
12468static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012469xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12470 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012471{
12472 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012473 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012474
12475 if (wild->any)
12476 return(1);
12477 else if (wild->nsSet != NULL) {
12478 xmlSchemaWildcardNsPtr cur;
12479
12480 cur = wild->nsSet;
12481 while (cur != NULL) {
12482 if (xmlStrEqual(cur->value, ns))
12483 return(1);
12484 cur = cur->next;
12485 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012486 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012487 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012488 return(1);
12489
Daniel Veillard3646d642004-06-02 19:19:14 +000012490 return(0);
12491}
12492
12493/**
12494 * xmlSchemaBuildAttributeValidation:
12495 * @ctxt: the schema parser context
12496 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012497 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012498 *
12499 * Builds the wildcard and the attribute uses on the given complex type.
12500 * Returns -1 if an internal error occurs, 0 otherwise.
12501 */
12502static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012503xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12504 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012505{
12506 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012507 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12508 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012509 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012510 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012511 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012512 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012513
Daniel Veillard01fa6152004-06-29 17:04:39 +000012514 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012515 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012516 * Complex Type Definition with complex content Schema Component.
12517 *
12518 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012519 * TODO: Add checks for absent referenced attribute declarations and
12520 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012521 */
12522 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012523 PERROR_INT("xmlSchemaBuildAttributeValidation",
12524 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012525 return (-1);
12526 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012527 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012528 PERROR_INT("xmlSchemaBuildAttributeValidation",
12529 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012530 return (-1);
12531 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012532 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012533 /*
12534 * Inherit the attribute uses of the base type.
12535 */
12536 /*
12537 * NOTE: It is allowed to "extend" the anyType complex type.
12538 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012539 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012540 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012541 for (cur = baseType->attributeUses; cur != NULL;
12542 cur = cur->next) {
12543 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012544 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12545 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012546 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012547 "building attribute uses of complexType", NULL);
12548 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012549 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012550 tmp->attr = cur->attr;
12551 tmp->next = NULL;
12552 if (type->attributeUses == NULL) {
12553 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012554 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012555 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012556 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012557 }
12558 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012559 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012560 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012561 /*
12562 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012563 */
12564 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12565 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012566 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012567 * NOTE: During the parse time, the wildcard is created on the complexType
12568 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012569 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012570 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012571 PERROR_INT("xmlSchemaBuildAttributeValidation",
12572 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012573 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012574 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012575
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012576 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12577 ((IS_ANYTYPE(baseType)) ||
12578 ((baseType != NULL) &&
12579 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12580 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012581 if (type->attributeWildcard != NULL) {
12582 /*
12583 * Union the complete wildcard with the base wildcard.
12584 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012585 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012586 baseType->attributeWildcard) == -1)
12587 return (-1);
12588 } else {
12589 /*
12590 * Just inherit the wildcard.
12591 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012592 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012593 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012594 * wildcard is shared.
12595 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012596 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012597 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012598 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012599
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012600 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12601 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012602 /*
12603 * Derivation Valid (Restriction, Complex)
12604 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012605 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012606 if (baseType->attributeWildcard == NULL) {
12607 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012608 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012609 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012610 "The type has an attribute wildcard, "
12611 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012612 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012613 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012614 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012615 } else if (xmlSchemaCheckCOSNSSubset(
12616 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012617 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012618 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012619 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012620 NULL, type, NULL,
12621 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012622 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012623 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12624 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012625 return (1);
12626 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012627 /* 4.3 Unless the {base type definition} is the ·ur-type
12628 * definition·, the complex type definition's {attribute
12629 * wildcard}'s {process contents} must be identical to or
12630 * stronger than the {base type definition}'s {attribute
12631 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012632 * than lax is stronger than skip.
12633 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012634 if ((! IS_ANYTYPE(baseType)) &&
12635 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012636 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012637 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012638 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012639 NULL, type, NULL,
12640 "The 'process contents' of the attribute wildcard is "
12641 "weaker than the one in the base type %s",
12642 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012643 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012644 return (1);
12645 }
12646 }
12647 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12648 /*
12649 * Derivation Valid (Extension)
12650 * At this point the type and the base have both, either
12651 * no wildcard or a wildcard.
12652 */
12653 if ((baseType->attributeWildcard != NULL) &&
12654 (baseType->attributeWildcard != type->attributeWildcard)) {
12655 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012656 if (xmlSchemaCheckCOSNSSubset(
12657 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012658 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012659 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012660 NULL, type, NULL,
12661 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012662 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012663 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12664 FREE_AND_NULL(str)
12665 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012666 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012667 }
12668 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012669
Daniel Veillard3646d642004-06-02 19:19:14 +000012670 /*
12671 * Gather attribute uses defined by this type.
12672 */
12673 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012674 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012675 &uses, &lastUse) == -1) {
12676 return (-1);
12677 }
12678 }
12679 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012680 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012681 * not have identical {name}s and {target namespace}s."
12682 *
12683 * For "extension" this is done further down.
12684 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012685 if ((uses != NULL) && ((type->flags &
12686 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012687 cur = uses;
12688 while (cur != NULL) {
12689 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012690 while (tmp != NULL) {
12691 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012692 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012693 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012694 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12695
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012696 xmlSchemaPAttrUseErr(pctxt,
12697 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12698 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012699 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012700 xmlSchemaFormatQName(&str,
12701 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12702 xmlSchemaGetAttrName(tmp->attr)));
12703 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012704 break;
12705 }
12706 tmp = tmp->next;
12707 }
12708 cur = cur->next;
12709 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012710 }
12711 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012712 /*
12713 * Derive by restriction.
12714 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012715 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012716 type->attributeUses = uses;
12717 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012718 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012719 const xmlChar *bEffValue;
12720 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012721
12722 cur = uses;
12723 while (cur != NULL) {
12724 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012725 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012726 base = type->attributeUses;
12727 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012728 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012729 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012730 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012731 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012732
12733 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012734
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012735 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012736 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12737 (base->attr->occurs ==
12738 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12739 /*
12740 * NOOP.
12741 */
12742 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012743 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12744 (base->attr->occurs ==
12745 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012746 /*
12747 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012748 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012749 xmlSchemaPAttrUseErr(pctxt,
12750 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12751 type, cur->attr,
12752 "The 'optional' use is inconsistent with a "
12753 "matching 'required' use of the base type",
12754 NULL);
12755 } else if ((cur->attr->occurs ==
12756 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12757 (base->attr->occurs ==
12758 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12759 /*
12760 * derivation-ok-restriction 3
12761 */
12762 xmlSchemaPCustomErr(pctxt,
12763 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12764 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012765 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012766 "attribute use '%s' of the base type is "
12767 "missing",
12768 xmlSchemaFormatQName(&str,
12769 xmlSchemaGetAttrTargetNsURI(base->attr),
12770 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012771 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012772 } else if (xmlSchemaCheckCOSSTDerivedOK(
12773 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12774
12775 /*
12776 * SPEC (2.1.2) "R's {attribute declaration}'s
12777 * {type definition} must be validly derived from
12778 * B's {type definition} given the empty set as
12779 * defined in Type Derivation OK (Simple) (§3.14.6)."
12780 */
12781 xmlSchemaPAttrUseErr(pctxt,
12782 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12783 type, cur->attr,
12784 "The attribute declaration's type "
12785 "definition is not validly derived from "
12786 "the corresponding definition in the "
12787 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012788 } else {
12789 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012790 * 2.1.3 [Definition:] Let the effective value
12791 * constraint of an attribute use be its {value
12792 * constraint}, if present, otherwise its {attribute
12793 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012794 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012795 xmlSchemaGetEffectiveValueConstraint(base->attr,
12796 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012797 /*
12798 * 2.1.3 ... one of the following must be true
12799 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012800 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012801 * ·absent· or default.
12802 */
12803 if ((bEffValue != NULL) &&
12804 (effFixed == 1)) {
12805 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012806
12807 xmlSchemaGetEffectiveValueConstraint(base->attr,
12808 &effFixed, &rEffValue, 0);
12809 /*
12810 * 2.1.3.2 R's ·effective value constraint· is
12811 * fixed with the same string as B's.
12812 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012813 */
12814 if ((effFixed == 0) ||
12815 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012816 xmlSchemaPAttrUseErr(pctxt,
12817 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12818 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012819 "The effective value constraint of the "
12820 "attribute use is inconsistent with "
12821 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012822 NULL);
12823 } else {
12824 /*
12825 * Override the attribute use.
12826 */
12827 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012828 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012829 } else
12830 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012831 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012832
Daniel Veillard3646d642004-06-02 19:19:14 +000012833 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012834 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012835 base = base->next;
12836 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012837
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012838 if ((!found) && (cur->attr->occurs !=
12839 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12840 /*
12841 * derivation-ok-restriction 2.2
12842 */
12843 if ((baseType->attributeWildcard == NULL) ||
12844 (xmlSchemaCheckCVCWildcardNamespace(
12845 baseType->attributeWildcard,
12846 cur->attr->targetNamespace) != 1)) {
12847 xmlSchemaPAttrUseErr(pctxt,
12848 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12849 type, cur->attr,
12850 "Neither a matching attribute use, "
12851 "nor a matching wildcard in the base type does exist",
12852 NULL);
12853 } else {
12854 /*
12855 * Add the attribute use.
12856 *
12857 * Note that this may lead to funny derivation error reports, if
12858 * multiple equal attribute uses exist; but this is not
12859 * allowed anyway, and it will be reported beforehand.
12860 */
12861 tmp = cur;
12862 if (prev != NULL)
12863 prev->next = cur->next;
12864 else
12865 uses = cur->next;
12866 cur = cur->next;
12867 tmp->next = NULL;
12868 if (type->attributeUses == NULL) {
12869 type->attributeUses = tmp;
12870 } else
12871 lastBaseUse->next = tmp;
12872 lastBaseUse = tmp;
12873
12874 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012875 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012876 }
12877 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012878 cur = cur->next;
12879 }
12880 if (uses != NULL)
12881 xmlSchemaFreeAttributeUseList(uses);
12882 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012883 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012884 /*
12885 * The spec allows only appending, and not other kinds of extensions.
12886 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012887 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012888 */
12889 if (uses != NULL) {
12890 if (type->attributeUses == NULL) {
12891 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012892 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012893 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012894 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012895 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012896 PERROR_INT("xmlSchemaBuildAttributeValidation",
12897 "no derivation method");
12898 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012899 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012900 /*
12901 * 3.4.6 -> Complex Type Definition Properties Correct
12902 */
12903 if (type->attributeUses != NULL) {
12904 cur = type->attributeUses;
12905 prev = NULL;
12906 while (cur != NULL) {
12907 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012908 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012909 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012910 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012911 * Note that this was already done for "restriction" and types derived from
12912 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012913 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012914 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12915 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012916 while (tmp != NULL) {
12917 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012918 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012919 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012920 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012921
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012922 xmlSchemaPAttrUseErr(pctxt,
12923 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12924 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012925 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012926 break;
12927 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012928 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012929 }
12930 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012931 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012932 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012933 * not have {type definition}s which are or are derived from ID.
12934 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012935 if ((cur->attr->subtypes != NULL) &&
12936 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12937 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012938 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012939 xmlSchemaPAttrUseErr(pctxt,
12940 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12941 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012942 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012943 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012944 NULL);
12945 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012946 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012947 id = cur;
12948 }
12949 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012950 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012951 * stage is to be able to catch dublicate attribute uses. So we had to keep
12952 * prohibited uses in the list as well.
12953 */
12954 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
12955 tmp = cur;
12956 if (prev == NULL)
12957 type->attributeUses = cur->next;
12958 else
12959 prev->next = cur->next;
12960 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012961 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000012962 } else {
12963 prev = cur;
12964 cur = cur->next;
12965 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012966 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012967 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012968 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012969 * TODO: This check should be removed if we are 100% sure of
12970 * the base type attribute uses already being built.
12971 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012972 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012973 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012974 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012975 PERROR_INT("xmlSchemaBuildAttributeValidation",
12976 "attribute uses not builded on base type");
12977 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012978 return (0);
12979}
12980
12981/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000012982 * xmlSchemaTypeFinalContains:
12983 * @schema: the schema
12984 * @type: the type definition
12985 * @final: the final
12986 *
12987 * Evaluates if a type definition contains the given "final".
12988 * This does take "finalDefault" into account as well.
12989 *
12990 * Returns 1 if the type does containt the given "final",
12991 * 0 otherwise.
12992 */
12993static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012994xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012995{
Daniel Veillard01fa6152004-06-29 17:04:39 +000012996 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012997 return (0);
12998 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012999 return (1);
13000 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013001 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013002}
13003
13004/**
13005 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13006 * @type: the Union Simple Type
13007 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013008 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013009 * returns NULL otherwise.
13010 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013011static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013012xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13013{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013014 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013015 if (type->memberTypes != NULL)
13016 return (type->memberTypes);
13017 else
13018 type = type->baseType;
13019 }
13020 return (NULL);
13021}
13022
13023/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013024 * xmlSchemaGetParticleTotalRangeMin:
13025 * @particle: the particle
13026 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013027 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013028 * (all and sequence) + (choice)
13029 *
13030 * Returns the minimun Effective Total Range.
13031 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013032static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013033xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013034{
13035 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013036 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013037 return (0);
13038 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013039 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013040 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013041 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013042
13043 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013044 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013045 while (part != NULL) {
13046 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13047 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013048 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013049 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013050 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013051 if (cur == 0)
13052 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013053 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013054 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013055 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013056 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013057 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013058 } else {
13059 /* <all> and <sequence> */
13060 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013061 xmlSchemaParticlePtr part =
13062 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013063
13064 if (part == NULL)
13065 return (0);
13066 do {
13067 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13068 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013069 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013070 else
13071 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013072 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013073 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013074 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013075 }
13076}
13077
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013078/**
13079 * xmlSchemaGetParticleTotalRangeMax:
13080 * @particle: the particle
13081 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013082 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013083 * (all and sequence) + (choice)
13084 *
13085 * Returns the maximum Effective Total Range.
13086 */
13087static int
13088xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13089{
13090 if ((particle->children == NULL) ||
13091 (particle->children->children == NULL))
13092 return (0);
13093 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13094 int max = -1, cur;
13095 xmlSchemaParticlePtr part =
13096 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013097
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013098 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13099 if (part->children == NULL)
13100 continue;
13101 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13102 (part->children->type == XML_SCHEMA_TYPE_ANY))
13103 cur = part->maxOccurs;
13104 else
13105 cur = xmlSchemaGetParticleTotalRangeMax(part);
13106 if (cur == UNBOUNDED)
13107 return (UNBOUNDED);
13108 if ((max < cur) || (max == -1))
13109 max = cur;
13110 }
13111 /* TODO: Handle overflows? */
13112 return (particle->maxOccurs * max);
13113 } else {
13114 /* <all> and <sequence> */
13115 int sum = 0, cur;
13116 xmlSchemaParticlePtr part =
13117 (xmlSchemaParticlePtr) particle->children->children;
13118
13119 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13120 if (part->children == NULL)
13121 continue;
13122 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13123 (part->children->type == XML_SCHEMA_TYPE_ANY))
13124 cur = part->maxOccurs;
13125 else
13126 cur = xmlSchemaGetParticleTotalRangeMax(part);
13127 if (cur == UNBOUNDED)
13128 return (UNBOUNDED);
13129 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13130 return (UNBOUNDED);
13131 sum += cur;
13132 }
13133 /* TODO: Handle overflows? */
13134 return (particle->maxOccurs * sum);
13135 }
13136}
13137
13138/**
13139 * xmlSchemaIsParticleEmptiable:
13140 * @particle: the particle
13141 *
13142 * Schema Component Constraint: Particle Emptiable
13143 * Checks whether the given particle is emptiable.
13144 *
13145 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013146 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013147static int
13148xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13149{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013150 /*
13151 * SPEC (1) "Its {min occurs} is 0."
13152 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013153 if ((particle == NULL) || (particle->minOccurs == 0) ||
13154 (particle->children == NULL))
13155 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013156 /*
13157 * SPEC (2) "Its {term} is a group and the minimum part of the
13158 * effective total range of that group, [...] is 0."
13159 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013160 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013161 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013162 return (1);
13163 }
13164 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013165}
13166
13167/**
13168 * xmlSchemaCheckCOSSTDerivedOK:
13169 * @type: the derived simple type definition
13170 * @baseType: the base type definition
13171 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013172 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013173 * Type Derivation OK (Simple) (cos-st-derived-OK)
13174 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013175 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013176 * derived from @baseType.
13177 *
13178 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013179 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013180static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013181xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13182 xmlSchemaTypePtr baseType,
13183 int subset)
13184{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013185 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013186 * 1 They are the same type definition.
13187 * TODO: The identy check might have to be more complex than this.
13188 */
13189 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013190 return (0);
13191 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013192 * 2.1 restriction is not in the subset, or in the {final}
13193 * of its own {base type definition};
13194 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013195 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013196 (xmlSchemaTypeFinalContains(type->baseType,
13197 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13198 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013199 }
13200 /* 2.2 */
13201 if (type->baseType == baseType) {
13202 /*
13203 * 2.2.1 D's ·base type definition· is B.
13204 */
13205 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013206 }
13207 /*
13208 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13209 * and is validly derived from B given the subset, as defined by this
13210 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013211 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013212 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013213 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013214 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013215 return (0);
13216 }
13217 /*
13218 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013219 * definition·.
13220 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013221 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013222 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013223 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013224 }
13225 /*
13226 * 2.2.4 B's {variety} is union and D is validly derived from a type
13227 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013228 * defined by this constraint.
13229 *
13230 * NOTE: This seems not to involve built-in types, since there is no
13231 * built-in Union Simple Type.
13232 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013233 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013234 xmlSchemaTypeLinkPtr cur;
13235
13236 cur = baseType->memberTypes;
13237 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013238 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013239 return (0);
13240 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013241 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013242 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013243
Daniel Veillard01fa6152004-06-29 17:04:39 +000013244 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13245}
13246
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013247/**
13248 * xmlSchemaCheckTypeDefCircularInternal:
13249 * @pctxt: the schema parser context
13250 * @ctxtType: the type definition
13251 * @ancestor: an ancestor of @ctxtType
13252 *
13253 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013254 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013255 *
13256 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13257 * circular, 0 otherwise.
13258 */
13259static int
13260xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13261 xmlSchemaTypePtr ctxtType,
13262 xmlSchemaTypePtr ancestor)
13263{
13264 int ret;
13265
13266 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13267 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013268
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013269 if (ctxtType == ancestor) {
13270 xmlSchemaPCustomErr(pctxt,
13271 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13272 NULL, ctxtType, GET_NODE(ctxtType),
13273 "The definition is circular", NULL);
13274 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13275 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013276 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13277 /*
13278 * Avoid inifinite recursion on circular types not yet checked.
13279 */
13280 return (0);
13281 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013282 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13283 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13284 ancestor->baseType);
13285 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13286 return (ret);
13287}
13288
13289/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013290 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013291 * @item: the complex/simple type definition
13292 * @ctxt: the parser context
13293 * @name: the name
13294 *
13295 * Checks for circular type definitions.
13296 */
13297static void
13298xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013299 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013300 const xmlChar * name ATTRIBUTE_UNUSED)
13301{
13302 if ((item == NULL) ||
13303 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13304 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13305 return;
13306 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13307
13308}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013309
13310/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013311 * xmlSchemaResolveTypeDefs:
13312 * @item: the complex/simple type definition
13313 * @ctxt: the parser context
13314 * @name: the name
13315 *
13316 * Checks for circular type definitions.
13317 */
13318static void
13319xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013320 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013321 const xmlChar * name ATTRIBUTE_UNUSED)
13322{
13323 if (typeDef == NULL)
13324 return;
13325
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013326 /*
13327 * Resolve the base type.
13328 */
13329 if (typeDef->baseType == NULL) {
13330 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13331 typeDef->base, typeDef->baseNs);
13332 if (typeDef->baseType == NULL) {
13333 xmlSchemaPResCompAttrErr(ctxt,
13334 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013335 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013336 "base", typeDef->base, typeDef->baseNs,
13337 XML_SCHEMA_TYPE_SIMPLE, NULL);
13338 return;
13339 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013340 }
13341 if (IS_SIMPLE_TYPE(typeDef)) {
13342 if (VARIETY_UNION(typeDef)) {
13343 /*
13344 * Resolve the memberTypes.
13345 */
13346 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13347 return;
13348 } else if (VARIETY_LIST(typeDef)) {
13349 /*
13350 * Resolve the itemType.
13351 */
13352 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13353 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13354 typeDef->ref, typeDef->refNs);
13355 if ((typeDef->subtypes == NULL) ||
13356 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13357 typeDef->subtypes = NULL;
13358 xmlSchemaPResCompAttrErr(ctxt,
13359 XML_SCHEMAP_SRC_RESOLVE,
13360 typeDef, typeDef->node,
13361 "itemType", typeDef->ref, typeDef->refNs,
13362 XML_SCHEMA_TYPE_SIMPLE, NULL);
13363 }
13364 }
13365 return;
13366 }
13367 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013368}
13369
13370
13371
13372/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013373 * xmlSchemaCheckSTPropsCorrect:
13374 * @ctxt: the schema parser context
13375 * @type: the simple type definition
13376 *
13377 * Checks st-props-correct.
13378 *
13379 * Returns 0 if the properties are correct,
13380 * if not, a positive error code and -1 on internal
13381 * errors.
13382 */
13383static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013384xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013385 xmlSchemaTypePtr type)
13386{
13387 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13388 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013389 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013390
Daniel Veillardc0826a72004-08-10 14:17:33 +000013391 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013392 /*
13393 * Schema Component Constraint: Simple Type Definition Properties Correct
13394 *
13395 * NOTE: This is somehow redundant, since we actually built a simple type
13396 * to have all the needed information; this acts as an self test.
13397 */
13398 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13399 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013400 /* Base type: If the datatype has been ·derived· by ·restriction·
13401 * then the Simple Type Definition component from which it is ·derived·,
13402 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013403 */
13404 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013405 /*
13406 * TODO: Think about: "modulo the impact of Missing
13407 * Sub-components (§5.3)."
13408 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013409 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013410 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013411 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013412 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013413 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013414
Daniel Veillard01fa6152004-06-29 17:04:39 +000013415 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013416 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013417 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013418 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013419 NULL, type, NULL,
13420 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013421 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013422 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013423 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13424 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013425 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13426 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13427 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013428 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013429 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013430 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013431 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013432 "the simple ur-type definition as base type, not '%s'",
13433 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013434 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013435 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13436 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013437 /*
13438 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013439 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013440 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13441 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013442 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013443 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013444 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013445 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013446 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13447 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013448 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013449
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013450 /*
13451 * 3 The {final} of the {base type definition} must not contain restriction.
13452 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013453 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013454 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13455 xmlSchemaPCustomErr(ctxt,
13456 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013457 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013458 "The 'final' of its base type '%s' must not contain "
13459 "'restriction'",
13460 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013461 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013462 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013463 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013464
13465 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013466 * 2 All simple type definitions must be derived ultimately from the ·simple
13467 * ur-type definition (so· circular definitions are disallowed). That is, it
13468 * must be possible to reach a built-in primitive datatype or the ·simple
13469 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013470 *
13471 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013472 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013473 return (0);
13474}
13475
13476/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013477 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013478 * @ctxt: the schema parser context
13479 * @type: the simple type definition
13480 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013481 * Schema Component Constraint:
13482 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13483
13484 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013485 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013486 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013487 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013488 * a positive error code otherwise.
13489 */
13490static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013491xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013492 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013493{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013494 xmlChar *str = NULL;
13495
Daniel Veillard01fa6152004-06-29 17:04:39 +000013496 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013497 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13498 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013499 return (-1);
13500 }
13501
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013502 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013503 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013504 /*
13505 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013506 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013507 */
13508 if (! VARIETY_ATOMIC(type->baseType)) {
13509 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013510 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013511 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013512 "The base type '%s' is not an atomic simple type",
13513 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013514 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013515 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13516 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013517 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013518 * restriction.
13519 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013520 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013521 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013522 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013523 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013524 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013525 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013526 "The final of its base type '%s' must not contain 'restriction'",
13527 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013528 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013529 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13530 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013531
13532 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013533 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013535 * Primitive datatypes.
13536 */
13537 if (type->facets != NULL) {
13538 xmlSchemaFacetPtr facet;
13539 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540
Daniel Veillard01fa6152004-06-29 17:04:39 +000013541 primitive = xmlSchemaGetPrimitiveType(type);
13542 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013543 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13544 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013545 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013546 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013547 facet = type->facets;
13548 do {
13549 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013550 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013551 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013552 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013553 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013554 }
13555 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013556 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013557 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013558 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013559 }
13560 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013561 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13562 * of the {base type definition} (call this BF),then the DF's {value}
13563 * must be a valid restriction of BF's {value} as defined in
13564 * [XML Schemas: Datatypes]."
13565 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013566 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013567 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013568 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013569 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013570 xmlSchemaTypePtr itemType = NULL;
13571
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013572 itemType = type->subtypes;
13573 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013574 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13575 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013576 return (-1);
13577 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013578 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013579 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013580 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013581 * 2.1 The {item type definition} must have a {variety} of atomic or
13582 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013583 * must be atomic).
13584 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013585 if ((! VARIETY_ATOMIC(itemType)) &&
13586 (! VARIETY_UNION(itemType))) {
13587 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013588 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013589 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013590 "The item type '%s' does not have a variety of atomic or union",
13591 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013592 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013593 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013594 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013595 xmlSchemaTypeLinkPtr member;
13596
13597 member = itemType->memberTypes;
13598 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013599 if (! VARIETY_ATOMIC(member->type)) {
13600 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013602 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013603 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013604 "member type '%s' of this item type is not atomic",
13605 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013606 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013607 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13608 }
13609 member = member->next;
13610 }
13611 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013612
13613 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013614 xmlSchemaFacetPtr facet;
13615 /*
13616 * This is the case if we have: <simpleType><list ..
13617 */
13618 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013619 * 2.3.1
13620 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013621 * contain list.
13622 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013623 if (xmlSchemaTypeFinalContains(itemType,
13624 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13625 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013626 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013627 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013628 "The final of its item type '%s' must not contain 'list'",
13629 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013630 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013631 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13632 }
13633 /*
13634 * 2.3.1.2 The {facets} must only contain the whiteSpace
13635 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013636 * OPTIMIZE TODO: the S4S already disallows any facet
13637 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013638 */
13639 if (type->facets != NULL) {
13640 facet = type->facets;
13641 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013642 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013643 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013644 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013645 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013646 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13647 }
13648 facet = facet->next;
13649 } while (facet != NULL);
13650 }
13651 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013652 * MAYBE TODO: (Hmm, not really) Datatypes states:
13653 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13654 * whose ·lexical space· allows space (such as string or anyURI)or
13655 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013656 * ·lexical space· allows space.
13657 */
13658 } else {
13659 /*
13660 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013661 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013662 */
13663 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013664 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013665 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13666 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013667 if (! VARIETY_LIST(type->baseType)) {
13668 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013669 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013670 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013671 "The base type '%s' must be a list type",
13672 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013673 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013674 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13675 }
13676 /*
13677 * 2.3.2.2 The {final} of the {base type definition} must not
13678 * contain restriction.
13679 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013680 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013681 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013682 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013683 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013684 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013685 "The 'final' of the base type '%s' must not contain 'restriction'",
13686 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013687 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013688 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13689 }
13690 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013691 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013692 * from the {base type definition}'s {item type definition} given
13693 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13694 */
13695 {
13696 xmlSchemaTypePtr baseItemType;
13697
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013698 baseItemType = type->baseType->subtypes;
13699 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013700 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13701 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013702 return (-1);
13703 }
13704 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013705 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13706 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013707 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013708 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013709 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013710 NULL, type, NULL,
13711 "The item type '%s' is not validly derived from "
13712 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013713 xmlSchemaGetComponentQName(&str, itemType),
13714 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13715 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013716
13717 FREE_AND_NULL(str)
13718 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013719 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013720 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13721 }
13722 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013723
Daniel Veillard01fa6152004-06-29 17:04:39 +000013724 if (type->facets != NULL) {
13725 xmlSchemaFacetPtr facet;
13726 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013727 /*
13728 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013729 * and enumeration facet components are allowed among the {facets}.
13730 */
13731 facet = type->facets;
13732 do {
13733 switch (facet->type) {
13734 case XML_SCHEMA_FACET_LENGTH:
13735 case XML_SCHEMA_FACET_MINLENGTH:
13736 case XML_SCHEMA_FACET_MAXLENGTH:
13737 case XML_SCHEMA_FACET_WHITESPACE:
13738 /*
13739 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013740 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013741 */
13742 case XML_SCHEMA_FACET_PATTERN:
13743 case XML_SCHEMA_FACET_ENUMERATION:
13744 break;
13745 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013746 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013747 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013748 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013749 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013750 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013751 * invalid facets.
13752 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013753 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013754 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013755 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013756 facet = facet->next;
13757 } while (facet != NULL);
13758 if (ok == 0)
13759 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13760 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013761 * SPEC (2.3.2.5) (same as 1.3.2)
13762 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013763 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013764 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013765 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013766 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013767 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013768 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013769 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013770 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013771 * atomic or list.
13772 */
13773 xmlSchemaTypeLinkPtr member;
13774
13775 member = type->memberTypes;
13776 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013777 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013778 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013779
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013780 if ((! VARIETY_ATOMIC(member->type)) &&
13781 (! VARIETY_LIST(member->type))) {
13782 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013783 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013784 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013785 "The member type '%s' is neither an atomic, nor a list type",
13786 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013787 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013788 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13789 }
13790 member = member->next;
13791 }
13792 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013793 * 3.3.1 If the {base type definition} is the ·simple ur-type
13794 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013795 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013796 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013797 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013798 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013799 * {final} which does not contain union.
13800 */
13801 member = type->memberTypes;
13802 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013803 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013804 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013805 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013806 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013807 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013808 "The 'final' of member type '%s' contains 'union'",
13809 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013810 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013811 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13812 }
13813 member = member->next;
13814 }
13815 /*
13816 * 3.3.1.2 The {facets} must be empty.
13817 */
13818 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013819 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013820 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013821 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013822 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013823 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13824 }
13825 } else {
13826 /*
13827 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013828 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013829 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013830 if (! VARIETY_UNION(type->baseType)) {
13831 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013832 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013833 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013834 "The base type '%s' is not a union type",
13835 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013836 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013837 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13838 }
13839 /*
13840 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13841 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013842 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013843 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013844 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013845 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013846 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013847 "The 'final' of its base type '%s' must not contain 'restriction'",
13848 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013849 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013850 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13851 }
13852 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013853 * 3.3.2.3 The {member type definitions}, in order, must be validly
13854 * derived from the corresponding type definitions in the {base
13855 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013856 * as defined in Type Derivation OK (Simple) (§3.14.6).
13857 */
13858 {
13859 xmlSchemaTypeLinkPtr baseMember;
13860
13861 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013862 * OPTIMIZE: if the type is restricting, it has no local defined
13863 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013864 * thus a check for equality can be skipped.
13865 */
13866 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013867 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013868 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013869 * types of it's base type. This check seems not necessary with
13870 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013871 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013872 */
13873 if (type->memberTypes != NULL) {
13874 member = type->memberTypes;
13875 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013876 if ((member == NULL) && (baseMember != NULL)) {
13877 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13878 "different number of member types in base");
13879 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013880 while (member != NULL) {
13881 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013882 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13883 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013884 }
13885 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013886 (xmlSchemaCheckCOSSTDerivedOK(
13887 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013888 xmlChar *strBMT = NULL, *strBT = NULL;
13889
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013890 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013891 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13892 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013893 "The member type %s is not validly "
13894 "derived from its corresponding member "
13895 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013896 xmlSchemaGetComponentQName(&str, member->type),
13897 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13898 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013899 FREE_AND_NULL(str)
13900 FREE_AND_NULL(strBMT)
13901 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013902 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013903 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013904 member = member->next;
13905 baseMember = baseMember->next;
13906 }
13907 }
13908 }
13909 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013910 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013911 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013912 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013913 if (type->facets != NULL) {
13914 xmlSchemaFacetPtr facet;
13915 int ok = 1;
13916
13917 facet = type->facets;
13918 do {
13919 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13920 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013921 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013922 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013923 NULL, type, facet);
13924 ok = 0;
13925 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013926 facet = facet->next;
13927 } while (facet != NULL);
13928 if (ok == 0)
13929 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013930
Daniel Veillard01fa6152004-06-29 17:04:39 +000013931 }
13932 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013933 * SPEC (3.3.2.5) (same as 1.3.2)
13934 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013935 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013936 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013937 */
13938 }
13939 }
13940
13941 return (0);
13942}
13943
13944/**
13945 * xmlSchemaCheckSRCSimpleType:
13946 * @ctxt: the schema parser context
13947 * @type: the simple type definition
13948 *
13949 * Checks crc-simple-type constraints.
13950 *
13951 * Returns 0 if the constraints are satisfied,
13952 * if not a positive error code and -1 on internal
13953 * errors.
13954 */
13955static int
13956xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
13957 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013958{
13959 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013960 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013961 * must satisfy the conditions set out in Constraints on Simple Type
13962 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013963 */
13964 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
13965 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
13966 /*
13967 * TODO: Removed this, since it got annoying to get an
13968 * extra error report, if anything failed until now.
13969 * Enable this if needed.
13970 */
13971 /*
13972 xmlSchemaPErr(ctxt, type->node,
13973 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013974 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000013975 "on simple type definitions.\n",
13976 type->name, NULL);
13977 */
13978 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
13979 }
13980
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013981 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013982 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013983 * src-simple-type.2 If the <restriction> alternative is chosen,
13984 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000013985 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013986 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013987 /*
13988 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013989 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013990 */
13991 } else if (VARIETY_LIST(type)) {
13992 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
13993 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000013994 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013995 *
13996 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013997 */
13998 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013999 xmlSchemaTypeLinkPtr member;
14000 xmlSchemaTypePtr ancestor, anySimpleType;
14001
14002 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14003
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014004 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14005 * the <union> alternative is chosen, there must not be any entries
14006 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000014007 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014008 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014009 member = type->memberTypes;
14010 while (member != NULL) {
14011 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014012 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014013 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014014 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014015 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014016 NULL, type, NULL,
14017 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014018 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014019 }
14020 if (IS_NOT_TYPEFIXED(ancestor))
14021 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014022 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014023 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014024 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014025 * type as item type, which in turn has a list ST as member
14026 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000014027 * was not yet performed.
14028 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014029 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014030
Daniel Veillard01fa6152004-06-29 17:04:39 +000014031 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014032 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014033 member = member->next;
14034 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014035 }
14036
14037 return (0);
14038}
14039
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014040static int
14041xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14042{
14043 if (ctxt->vctxt == NULL) {
14044 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14045 if (ctxt->vctxt == NULL) {
14046 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014047 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014048 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014049 "failed to create a temp. validation context.\n",
14050 NULL, NULL);
14051 return (-1);
14052 }
14053 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014054 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014055 }
14056 return (0);
14057}
14058
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014059static int
14060xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14061 xmlNodePtr node,
14062 xmlSchemaTypePtr type,
14063 const xmlChar *value,
14064 xmlSchemaValPtr *retVal,
14065 int fireErrors,
14066 int normalize,
14067 int isNormalized);
14068
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014069/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014070 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014071 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014072 * @type: the simple type definition
14073 * @value: the default value
14074 * @node: an optional node (the holder of the value)
14075 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014076 * Schema Component Constraint: Element Default Valid (Immediate)
14077 * (cos-valid-default)
14078 * This will be used by the parser only. For the validator there's
14079 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014080 *
14081 * Returns 0 if the constraints are satisfied,
14082 * if not, a positive error code and -1 on internal
14083 * errors.
14084 */
14085static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014086xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14087 xmlNodePtr node,
14088 xmlSchemaTypePtr type,
14089 const xmlChar *value,
14090 xmlSchemaValPtr *val)
14091{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014092 int ret = 0;
14093
14094 /*
14095 * cos-valid-default:
14096 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014097 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014098 * definition the appropriate case among the following must be true:
14099 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014100 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014101 /*
14102 * Complex type.
14103 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014104 * SPEC (2.1) "its {content type} must be a simple type definition
14105 * or mixed."
14106 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014107 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014108 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014109 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014110 if ((! HAS_SIMPLE_CONTENT(type)) &&
14111 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14112 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014113 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014114 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014115 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014116 "For a string to be a valid default, the type definition "
14117 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014118 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014119 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14120 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014121 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014122 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014123 * 1 If the type definition is a simple type definition, then the string
14124 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014125 * Valid (§3.14.4).
14126 *
14127 * AND
14128 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014129 * 2.2.1 If the {content type} is a simple type definition, then the
14130 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014131 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014132 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014133 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014134 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14135 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014136 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014137 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14138 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014139 else
14140 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014141
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014142 if (ret < 0) {
14143 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14144 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014145 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014146
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014147 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014148}
14149
14150/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014151 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014152 * @ctxt: the schema parser context
14153 * @type: the complex type definition
14154 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014155 *.(4.6) Constraints on Complex Type Definition Schema Components
14156 * Schema Component Constraint:
14157 * Complex Type Definition Properties Correct (ct-props-correct)
14158 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014159 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014160 * Returns 0 if the constraints are satisfied, a positive
14161 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014162 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014163static int
14164xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14165 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014166{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014167 /*
14168 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14169 *
14170 * SPEC (1) "The values of the properties of a complex type definition must
14171 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014172 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014173 * Sub-components (§5.3)."
14174 */
14175 if ((type->baseType != NULL) &&
14176 (IS_SIMPLE_TYPE(type->baseType)) &&
14177 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14178 /*
14179 * SPEC (2) "If the {base type definition} is a simple type definition,
14180 * the {derivation method} must be extension."
14181 */
14182 xmlSchemaPCustomErr(pctxt,
14183 XML_SCHEMAP_SRC_CT_1,
14184 NULL, type, NULL,
14185 "If the base type is a simple type, the derivation method must be "
14186 "'extension'", NULL);
14187 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014188 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014189 /*
14190 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14191 * definition·. That is, it must be possible to reach the ·ur-type
14192 * definition by repeatedly following the {base type definition}."
14193 *
14194 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14195 *
14196 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014197 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014198 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14199 * must not have {type definition}s which are or are derived from ID."
14200 *
14201 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14202 */
14203 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014204}
14205
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014206static int
14207xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14208 xmlSchemaTypePtr typeB)
14209{
14210 /*
14211 * TODO: This should implement component-identity
14212 * in the future.
14213 */
14214 if ((typeA == NULL) || (typeB == NULL))
14215 return (0);
14216 return (typeA == typeB);
14217}
14218
14219/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014220 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014221 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014222 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014223 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014224 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014225 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014226 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014227 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14228 *
14229 * STATUS: completed
14230 *
14231 * Returns 0 if the constraints are satisfied, or 1
14232 * if not.
14233 */
14234static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014235xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014236 xmlSchemaTypePtr baseType,
14237 int set)
14238{
14239 int equal = xmlSchemaAreEqualTypes(type, baseType);
14240 /* TODO: Error codes. */
14241 /*
14242 * SPEC "For a complex type definition (call it D, for derived)
14243 * to be validly derived from a type definition (call this
14244 * B, for base) given a subset of {extension, restriction}
14245 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014246 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014247 if (! equal) {
14248 /*
14249 * SPEC (1) "If B and D are not the same type definition, then the
14250 * {derivation method} of D must not be in the subset."
14251 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014252 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014253 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014254 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014255 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014256 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014257 } else {
14258 /*
14259 * SPEC (2.1) "B and D must be the same type definition."
14260 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014261 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014262 }
14263 /*
14264 * SPEC (2.2) "B must be D's {base type definition}."
14265 */
14266 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014267 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014268 /*
14269 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14270 * definition·."
14271 */
14272 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014273 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014274
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014275 if (IS_COMPLEX_TYPE(type->baseType)) {
14276 /*
14277 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14278 * must be validly derived from B given the subset as defined by this
14279 * constraint."
14280 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014281 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014282 baseType, set));
14283 } else {
14284 /*
14285 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14286 * must be validly derived from B given the subset as defined in Type
14287 * Derivation OK (Simple) (§3.14.6).
14288 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014289 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14290 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014291}
14292
14293/**
14294 * xmlSchemaCheckCOSDerivedOK:
14295 * @type: the derived simple type definition
14296 * @baseType: the base type definition
14297 *
14298 * Calls:
14299 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014300 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014301 * Checks wheter @type can be validly derived from @baseType.
14302 *
14303 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014304 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014305static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014306xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014307 xmlSchemaTypePtr baseType,
14308 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014309{
14310 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014311 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014312 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014313 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014314}
14315
William M. Brack2f2a6632004-08-20 23:09:47 +000014316/**
14317 * xmlSchemaCheckCOSCTExtends:
14318 * @ctxt: the schema parser context
14319 * @type: the complex type definition
14320 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014321 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014322 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014323 * Derivation Valid (Extension) (cos-ct-extends)
14324 *
14325 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014326 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014327 * (1.5)
14328 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014329 *
14330 * Returns 0 if the constraints are satisfied, a positive
14331 * error code if not and -1 if an internal error occured.
14332 */
14333static int
14334xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14335 xmlSchemaTypePtr type)
14336{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014337 xmlSchemaTypePtr base = type->baseType;
14338 /*
14339 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14340 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014341 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014342 /*
14343 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014344 * then all of the following must be true:"
14345 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014346 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14347 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014348 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014349 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014350 */
14351 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14352 xmlSchemaPCustomErr(ctxt,
14353 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14354 NULL, type, NULL,
14355 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014356 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014357 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14358 }
14359 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014360 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014361 * uses}
14362 * of the complex type definition itself, that is, for every attribute
14363 * use in the {attribute uses} of the {base type definition}, there
14364 * must be an attribute use in the {attribute uses} of the complex
14365 * type definition itself whose {attribute declaration} has the same
14366 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014367 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014368 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014369 * NOTE (1.2): This will be already satisfied by the way the attribute
14370 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14371 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014372 */
14373
14374 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014375 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14376 * definition must also have one, and the base type definition's
14377 * {attribute wildcard}'s {namespace constraint} must be a subset
14378 * of the complex type definition's {attribute wildcard}'s {namespace
14379 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014380 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014381 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014382 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014383 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014384 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014385 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014386 if ((type->contentTypeDef != NULL) &&
14387 (type->contentTypeDef == base->contentTypeDef)) {
14388 /*
14389 * SPEC (1.4.1) "The {content type} of the {base type definition}
14390 * and the {content type} of the complex type definition itself
14391 * must be the same simple type definition"
14392 * PASS
14393 */
14394 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14395 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14396 /*
14397 * SPEC (1.4.2) "The {content type} of both the {base type
14398 * definition} and the complex type definition itself must
14399 * be empty."
14400 * PASS
14401 */
14402 } else {
14403 /*
14404 * SPEC (1.4.3) "All of the following must be true:"
14405 */
14406 if (type->subtypes == NULL) {
14407 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014408 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014409 * definition itself must specify a particle.
14410 */
14411 xmlSchemaPCustomErr(ctxt,
14412 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14413 NULL, type, NULL,
14414 "The content type must specify a particle", NULL);
14415 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14416 }
14417 /*
14418 * SPEC (1.4.3.2) "One of the following must be true:"
14419 */
14420 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14421 /*
14422 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14423 * definition} must be empty.
14424 * PASS
14425 */
14426 } else {
14427 /*
14428 * SPEC (1.4.3.2.2) "All of the following must be true:"
14429 */
14430 if ((type->contentType != base->contentType) ||
14431 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14432 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14433 /*
14434 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14435 * or both must be element-only."
14436 */
14437 xmlSchemaPCustomErr(ctxt,
14438 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14439 NULL, type, NULL,
14440 "The content type of both, the type and its base "
14441 "type, must either 'mixed' or 'element-only'", NULL);
14442 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014443 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014444 /*
14445 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14446 * complex type definition must be a ·valid extension·
14447 * of the {base type definition}'s particle, as defined
14448 * in Particle Valid (Extension) (§3.9.6)."
14449 *
14450 * NOTE that we won't check "Particle Valid (Extension)",
14451 * since it is ensured by the derivation process in
14452 * xmlSchemaTypeFixup(). We need to implement this when heading
14453 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014454 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014455 }
14456 /*
14457 * TODO (1.5)
14458 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014459 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014460 } else {
14461 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014462 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014463 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014464 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014465 if (type->contentTypeDef != base) {
14466 /*
14467 * SPEC (2.1) "The {content type} must be the same simple type
14468 * definition."
14469 */
14470 xmlSchemaPCustomErr(ctxt,
14471 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14472 NULL, type, NULL,
14473 "The content type must be the simple base type", NULL);
14474 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14475 }
14476 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14477 /*
14478 * SPEC (2.2) "The {final} of the {base type definition} must not
14479 * contain extension"
14480 * NOTE that this is the same as (1.1).
14481 */
14482 xmlSchemaPCustomErr(ctxt,
14483 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14484 NULL, type, NULL,
14485 "The 'final' of the base type definition "
14486 "contains 'extension'", NULL);
14487 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014488 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014489 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014490 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014491}
14492
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014493/**
14494 * xmlSchemaCheckDerivationOKRestriction:
14495 * @ctxt: the schema parser context
14496 * @type: the complex type definition
14497 *
14498 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014499 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014500 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14501 *
14502 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014503 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014504 * (5.4.2), (5.2.2.1)
14505 *
14506 * Returns 0 if the constraints are satisfied, a positive
14507 * error code if not and -1 if an internal error occured.
14508 */
14509static int
14510xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14511 xmlSchemaTypePtr type)
14512{
14513 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014514
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014515 /*
14516 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14517 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014518 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014519 base = type->baseType;
14520 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14521 /*
14522 * SPEC (1) "The {base type definition} must be a complex type
14523 * definition whose {final} does not contain restriction."
14524 */
14525 xmlSchemaPCustomErr(ctxt,
14526 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14527 NULL, type, NULL,
14528 "The 'final' of the base type definition "
14529 "contains 'restriction'", NULL);
14530 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14531 }
14532 /*
14533 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14534 *
14535 * SPEC (5) "One of the following must be true:"
14536 */
14537 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14538 /*
14539 * SPEC (5.1) "The {base type definition} must be the
14540 * ·ur-type definition·."
14541 * PASS
14542 */
14543 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14544 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14545 /*
14546 * SPEC (5.2.1) "The {content type} of the complex type definition
14547 * must be a simple type definition"
14548 *
14549 * SPEC (5.2.2) "One of the following must be true:"
14550 */
14551 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14552 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14553 /*
14554 * SPEC (5.2.2.1) "The {content type} of the {base type
14555 * definition} must be a simple type definition from which
14556 * the {content type} is validly derived given the empty
14557 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14558 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014559 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014560 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14561 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014562 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014563 /*
14564 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14565 * and have a particle which is ·emptiable· as defined in
14566 * Particle Emptiable (§3.9.6)."
14567 * PASS
14568 */
14569 } else {
14570 xmlSchemaPCustomErr(ctxt,
14571 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14572 NULL, type, NULL,
14573 "The content type of the base type must be either "
14574 "a simple type or 'mixed' and an emptiable particle", NULL);
14575 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14576 }
14577 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14578 /*
14579 * SPEC (5.3.1) "The {content type} of the complex type itself must
14580 * be empty"
14581 */
14582 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14583 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014584 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014585 * definition} must also be empty."
14586 * PASS
14587 */
14588 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14589 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14590 xmlSchemaIsParticleEmptiable(
14591 (xmlSchemaParticlePtr) base->subtypes)) {
14592 /*
14593 * SPEC (5.3.2.2) "The {content type} of the {base type
14594 * definition} must be elementOnly or mixed and have a particle
14595 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14596 * PASS
14597 */
14598 } else {
14599 xmlSchemaPCustomErr(ctxt,
14600 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14601 NULL, type, NULL,
14602 "The content type of the base type must be either "
14603 "empty or 'mixed' (or 'elements-only') and an emptiable "
14604 "particle", NULL);
14605 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14606 }
14607 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014608 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014609 /*
14610 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14611 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014612 */
14613 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14614 /*
14615 * SPEC (5.4.1.2) "The {content type} of the complex type
14616 * definition itself and of the {base type definition} must be
14617 * mixed"
14618 */
14619 xmlSchemaPCustomErr(ctxt,
14620 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14621 NULL, type, NULL,
14622 "If the content type is 'mixed', then the content type of the "
14623 "base type must also be 'mixed'", NULL);
14624 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14625 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014626 /*
14627 * SPEC (5.4.2) "The particle of the complex type definition itself
14628 * must be a ·valid restriction· of the particle of the {content
14629 * type} of the {base type definition} as defined in Particle Valid
14630 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014631 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014632 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014633 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014634 } else {
14635 xmlSchemaPCustomErr(ctxt,
14636 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14637 NULL, type, NULL,
14638 "The type is not a valid restriction of its base type", NULL);
14639 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14640 }
14641 return (0);
14642}
14643
14644/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014645 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014646 * @ctxt: the schema parser context
14647 * @type: the complex type definition
14648 *
14649 * (3.4.6) Constraints on Complex Type Definition Schema Components
14650 *
14651 * Returns 0 if the constraints are satisfied, a positive
14652 * error code if not and -1 if an internal error occured.
14653 */
14654static int
14655xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14656 xmlSchemaTypePtr type)
14657{
14658 int ret;
14659 /*
14660 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014661 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014662 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14663 if (ret != 0)
14664 return (ret);
14665 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14666 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14667 else
14668 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14669 return (ret);
14670}
14671
14672/**
14673 * xmlSchemaCheckSRCCT:
14674 * @ctxt: the schema parser context
14675 * @type: the complex type definition
14676 *
14677 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014678 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014679 * Complex Type Definition Representation OK (src-ct)
14680 *
14681 * Returns 0 if the constraints are satisfied, a positive
14682 * error code if not and -1 if an internal error occured.
14683 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014684static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014685xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014686 xmlSchemaTypePtr type)
14687{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014688 xmlSchemaTypePtr base;
14689 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014690
14691 /*
14692 * TODO: Adjust the error codes here, as I used
14693 * XML_SCHEMAP_SRC_CT_1 only yet.
14694 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014695 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014696 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014697 /*
14698 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014699 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014700 * must be a complex type definition;
14701 */
14702 if (! IS_COMPLEX_TYPE(base)) {
14703 xmlChar *str = NULL;
14704 xmlSchemaPCustomErr(ctxt,
14705 XML_SCHEMAP_SRC_CT_1,
14706 NULL, type, type->node,
14707 "If using <complexContent>, the base type is expected to be "
14708 "a complex type. The base type '%s' is a simple type",
14709 xmlSchemaFormatQName(&str, base->targetNamespace,
14710 base->name));
14711 FREE_AND_NULL(str)
14712 return (XML_SCHEMAP_SRC_CT_1);
14713 }
14714 } else {
14715 /*
14716 * SPEC
14717 * 2 If the <simpleContent> alternative is chosen, all of the
14718 * following must be true:
14719 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14720 * base [attribute] must be one of the following:
14721 */
14722 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014723 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014724 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14725 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014726 /*
14727 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014728 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014729 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014730 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014731 xmlSchemaPCustomErr(ctxt,
14732 XML_SCHEMAP_SRC_CT_1,
14733 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014734 "If using <simpleContent> and <restriction>, the base "
14735 "type must be a complex type. The base type '%s' is "
14736 "a simple type",
14737 xmlSchemaFormatQName(&str, base->targetNamespace,
14738 base->name));
14739 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014740 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014741 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014742 } else {
14743 /* Base type is a complex type. */
14744 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14745 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14746 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014747 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014748 * simple type definition;
14749 * PASS
14750 */
14751 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014752 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014753 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014754 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014755 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014756 type->name);
14757 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014758 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014759 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14760 (type->flags &
14761 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014762
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014763 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014764 * 2.1.2 only if the <restriction> alternative is also
14765 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014766 * is mixed and a particle emptiable.
14767 */
14768 if (! xmlSchemaIsParticleEmptiable(
14769 (xmlSchemaParticlePtr) base->subtypes)) {
14770 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014771 } else
14772 /*
14773 * Attention: at this point the <simpleType> child is in
14774 * ->contentTypeDef (put there during parsing).
14775 */
14776 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014777 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014778 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014779 * 2.2 If clause 2.1.2 above is satisfied, then there
14780 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014781 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014782 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014783 /* TODO: Change error code to ..._SRC_CT_2_2. */
14784 xmlSchemaPCustomErr(ctxt,
14785 XML_SCHEMAP_SRC_CT_1,
14786 NULL, type, NULL,
14787 "A <simpleType> is expected among the children "
14788 "of <restriction>, if <simpleContent> is used and "
14789 "the base type '%s' is a complex type",
14790 xmlSchemaFormatQName(&str, base->targetNamespace,
14791 base->name));
14792 FREE_AND_NULL(str)
14793 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014794 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014795 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014796 ret = XML_SCHEMAP_SRC_CT_1;
14797 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014798 }
14799 if (ret > 0) {
14800 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014801 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014802 xmlSchemaPCustomErr(ctxt,
14803 XML_SCHEMAP_SRC_CT_1,
14804 NULL, type, NULL,
14805 "If <simpleContent> and <restriction> is used, the "
14806 "base type must be a simple type or a complex type with "
14807 "mixed content and particle emptiable. The base type "
14808 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014809 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014810 base->name));
14811 } else {
14812 xmlSchemaPCustomErr(ctxt,
14813 XML_SCHEMAP_SRC_CT_1,
14814 NULL, type, NULL,
14815 "If <simpleContent> and <extension> is used, the "
14816 "base type must be a simple type. The base type '%s' "
14817 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014818 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014819 base->name));
14820 }
14821 FREE_AND_NULL(str)
14822 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014823 }
14824 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014825 * SPEC (3) "The corresponding complex type definition component must
14826 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014827 * Definition Schema Components (§3.4.6);"
14828 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014829 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014830 /*
14831 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014832 * above for {attribute wildcard} is satisfied, the intensional
14833 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014834 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014835 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014836 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014837 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014838}
William M. Brack2f2a6632004-08-20 23:09:47 +000014839
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014840#ifdef ENABLE_PARTICLE_RESTRICTION
14841/**
14842 * xmlSchemaCheckParticleRangeOK:
14843 * @ctxt: the schema parser context
14844 * @type: the complex type definition
14845 *
14846 * (3.9.6) Constraints on Particle Schema Components
14847 * Schema Component Constraint:
14848 * Occurrence Range OK (range-ok)
14849 *
14850 * STATUS: complete
14851 *
14852 * Returns 0 if the constraints are satisfied, a positive
14853 * error code if not and -1 if an internal error occured.
14854 */
14855static int
14856xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14857 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014858{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014859 if (rmin < bmin)
14860 return (1);
14861 if ((bmax != UNBOUNDED) &&
14862 (rmax > bmax))
14863 return (1);
14864 return (0);
14865}
14866
14867/**
14868 * xmlSchemaCheckRCaseNameAndTypeOK:
14869 * @ctxt: the schema parser context
14870 * @r: the restricting element declaration particle
14871 * @b: the base element declaration particle
14872 *
14873 * (3.9.6) Constraints on Particle Schema Components
14874 * Schema Component Constraint:
14875 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14876 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014877 *
14878 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014879 * MISSING (3.2.3)
14880 * CLARIFY: (3.2.2)
14881 *
14882 * Returns 0 if the constraints are satisfied, a positive
14883 * error code if not and -1 if an internal error occured.
14884 */
14885static int
14886xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14887 xmlSchemaParticlePtr r,
14888 xmlSchemaParticlePtr b)
14889{
14890 xmlSchemaElementPtr elemR, elemB;
14891
14892 /* TODO: Error codes (rcase-NameAndTypeOK). */
14893 elemR = (xmlSchemaElementPtr) r->children;
14894 elemB = (xmlSchemaElementPtr) b->children;
14895 /*
14896 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14897 * the same."
14898 */
14899 if ((elemR != elemB) &&
14900 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14901 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14902 return (1);
14903 /*
14904 * SPEC (2) "R's occurrence range is a valid restriction of B's
14905 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14906 */
14907 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14908 b->minOccurs, b->maxOccurs) != 0)
14909 return (1);
14910 /*
14911 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14912 * {scope} are global."
14913 */
14914 if (elemR == elemB)
14915 return (0);
14916 /*
14917 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14918 */
14919 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14920 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14921 return (1);
14922 /*
14923 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14924 * or is not fixed, or R's declaration's {value constraint} is fixed
14925 * with the same value."
14926 */
14927 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14928 ((elemR->value == NULL) ||
14929 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14930 /* TODO: Equality of the initial value or normalized or canonical? */
14931 (! xmlStrEqual(elemR->value, elemB->value))))
14932 return (1);
14933 /*
14934 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14935 * definitions} is a subset of B's declaration's {identity-constraint
14936 * definitions}, if any."
14937 */
14938 if (elemB->idcs != NULL) {
14939 /* TODO */
14940 }
14941 /*
14942 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14943 * superset of B's declaration's {disallowed substitutions}."
14944 */
14945 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14946 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14947 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14948 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14949 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14950 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14951 return (1);
14952 /*
14953 * SPEC (3.2.5) "R's {type definition} is validly derived given
14954 * {extension, list, union} from B's {type definition}"
14955 *
14956 * BADSPEC TODO: What's the point of adding "list" and "union" to the
14957 * set, if the corresponding constraints handle "restriction" and
14958 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014959 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014960 */
14961 {
14962 int set = 0;
14963
14964 set |= SUBSET_EXTENSION;
14965 set |= SUBSET_LIST;
14966 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014967 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014968 elemB->subtypes, set) != 0)
14969 return (1);
14970 }
14971 return (0);
14972}
14973
14974/**
14975 * xmlSchemaCheckRCaseNSCompat:
14976 * @ctxt: the schema parser context
14977 * @r: the restricting element declaration particle
14978 * @b: the base wildcard particle
14979 *
14980 * (3.9.6) Constraints on Particle Schema Components
14981 * Schema Component Constraint:
14982 * Particle Derivation OK (Elt:Any -- NSCompat)
14983 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014984 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014985 * STATUS: complete
14986 *
14987 * Returns 0 if the constraints are satisfied, a positive
14988 * error code if not and -1 if an internal error occured.
14989 */
14990static int
14991xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
14992 xmlSchemaParticlePtr r,
14993 xmlSchemaParticlePtr b)
14994{
14995 /* TODO:Error codes (rcase-NSCompat). */
14996 /*
14997 * SPEC "For an element declaration particle to be a ·valid restriction·
14998 * of a wildcard particle all of the following must be true:"
14999 *
15000 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15001 * with respect to the wildcard's {namespace constraint} as defined by
15002 * Wildcard allows Namespace Name (§3.10.4)."
15003 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015004 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015005 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15006 return (1);
15007 /*
15008 * SPEC (2) "R's occurrence range is a valid restriction of B's
15009 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15010 */
15011 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15012 b->minOccurs, b->maxOccurs) != 0)
15013 return (1);
15014
15015 return (0);
15016}
15017
15018/**
15019 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15020 * @ctxt: the schema parser context
15021 * @r: the restricting element declaration particle
15022 * @b: the base model group particle
15023 *
15024 * (3.9.6) Constraints on Particle Schema Components
15025 * Schema Component Constraint:
15026 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15027 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015028 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015029 * STATUS: TODO
15030 *
15031 * Returns 0 if the constraints are satisfied, a positive
15032 * error code if not and -1 if an internal error occured.
15033 */
15034static int
15035xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15036 xmlSchemaParticlePtr r,
15037 xmlSchemaParticlePtr b)
15038{
15039 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15040 TODO
15041 return (0);
15042}
15043
15044/**
15045 * xmlSchemaCheckRCaseNSSubset:
15046 * @ctxt: the schema parser context
15047 * @r: the restricting wildcard particle
15048 * @b: the base wildcard particle
15049 *
15050 * (3.9.6) Constraints on Particle Schema Components
15051 * Schema Component Constraint:
15052 * Particle Derivation OK (Any:Any -- NSSubset)
15053 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015054 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015055 * STATUS: complete
15056 *
15057 * Returns 0 if the constraints are satisfied, a positive
15058 * error code if not and -1 if an internal error occured.
15059 */
15060static int
15061xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15062 xmlSchemaParticlePtr r,
15063 xmlSchemaParticlePtr b,
15064 int isAnyTypeBase)
15065{
15066 /* TODO: Error codes (rcase-NSSubset). */
15067 /*
15068 * SPEC (1) "R's occurrence range is a valid restriction of B's
15069 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15070 */
15071 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15072 b->minOccurs, b->maxOccurs))
15073 return (1);
15074 /*
15075 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15076 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15077 */
15078 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15079 (xmlSchemaWildcardPtr) b->children))
15080 return (1);
15081 /*
15082 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15083 * definition·, R's {process contents} must be identical to or stronger
15084 * than B's {process contents}, where strict is stronger than lax is
15085 * stronger than skip."
15086 */
15087 if (! isAnyTypeBase) {
15088 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15089 ((xmlSchemaWildcardPtr) b->children)->processContents)
15090 return (1);
15091 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015092
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015093 return (0);
15094}
15095
15096/**
15097 * xmlSchemaCheckCOSParticleRestrict:
15098 * @ctxt: the schema parser context
15099 * @type: the complex type definition
15100 *
15101 * (3.9.6) Constraints on Particle Schema Components
15102 * Schema Component Constraint:
15103 * Particle Valid (Restriction) (cos-particle-restrict)
15104 *
15105 * STATUS: TODO
15106 *
15107 * Returns 0 if the constraints are satisfied, a positive
15108 * error code if not and -1 if an internal error occured.
15109 */
15110static int
15111xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15112 xmlSchemaParticlePtr r,
15113 xmlSchemaParticlePtr b)
15114{
15115 int ret = 0;
15116
15117 /*part = GET_PARTICLE(type);
15118 basePart = GET_PARTICLE(base);
15119 */
15120
15121 TODO
15122
15123 /*
15124 * SPEC (1) "They are the same particle."
15125 */
15126 if (r == b)
15127 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015128
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015129
15130 return (0);
15131}
15132
15133/**
15134 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15135 * @ctxt: the schema parser context
15136 * @r: the model group particle
15137 * @b: the base wildcard 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/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015142 * NSRecurseCheckCardinality)
15143 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015144 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015145 * STATUS: TODO: subst-groups
15146 *
15147 * Returns 0 if the constraints are satisfied, a positive
15148 * error code if not and -1 if an internal error occured.
15149 */
15150static int
15151xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15152 xmlSchemaParticlePtr r,
15153 xmlSchemaParticlePtr b)
15154{
15155 xmlSchemaParticlePtr part;
15156 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15157 if ((r->children == NULL) || (r->children->children == NULL))
15158 return (-1);
15159 /*
15160 * SPEC "For a group particle to be a ·valid restriction· of a
15161 * wildcard particle..."
15162 *
15163 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015164 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015165 * Particle Valid (Restriction) (§3.9.6)."
15166 */
15167 part = (xmlSchemaParticlePtr) r->children->children;
15168 do {
15169 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15170 return (1);
15171 part = (xmlSchemaParticlePtr) part->next;
15172 } while (part != NULL);
15173 /*
15174 * SPEC (2) "The effective total range of the group [...] is a
15175 * valid restriction of B's occurrence range as defined by
15176 * Occurrence Range OK (§3.9.6)."
15177 */
15178 if (xmlSchemaCheckParticleRangeOK(
15179 xmlSchemaGetParticleTotalRangeMin(r),
15180 xmlSchemaGetParticleTotalRangeMax(r),
15181 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015182 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015183 return (0);
15184}
15185
15186/**
15187 * xmlSchemaCheckRCaseRecurse:
15188 * @ctxt: the schema parser context
15189 * @r: the <all> or <sequence> model group particle
15190 * @b: the base <all> or <sequence> model group particle
15191 *
15192 * (3.9.6) Constraints on Particle Schema Components
15193 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015194 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015195 Recurse)
15196 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015197 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015198 * STATUS: ?
15199 * TODO: subst-groups
15200 *
15201 * Returns 0 if the constraints are satisfied, a positive
15202 * error code if not and -1 if an internal error occured.
15203 */
15204static int
15205xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15206 xmlSchemaParticlePtr r,
15207 xmlSchemaParticlePtr b)
15208{
15209 /* xmlSchemaParticlePtr part; */
15210 /* TODO: Error codes (rcase-Recurse). */
15211 if ((r->children == NULL) || (b->children == NULL) ||
15212 (r->children->type != b->children->type))
15213 return (-1);
15214 /*
15215 * SPEC "For an all or sequence group particle to be a ·valid
15216 * restriction· of another group particle with the same {compositor}..."
15217 *
15218 * SPEC (1) "R's occurrence range is a valid restriction of B's
15219 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15220 */
15221 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15222 b->minOccurs, b->maxOccurs))
15223 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015224
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015225
15226 return (0);
15227}
15228
15229#endif
15230
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015231#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15232 xmlSchemaPCustomErrExt(pctxt, \
15233 XML_SCHEMAP_INVALID_FACET_VALUE, \
15234 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15235 "It is an error for both '%s' and '%s' to be specified on the "\
15236 "same type definition", \
15237 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15238 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15239
15240#define FACET_RESTR_ERR(fac1, msg) \
15241 xmlSchemaPCustomErr(pctxt, \
15242 XML_SCHEMAP_INVALID_FACET_VALUE, \
15243 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015244 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015245
15246#define FACET_RESTR_FIXED_ERR(fac) \
15247 xmlSchemaPCustomErr(pctxt, \
15248 XML_SCHEMAP_INVALID_FACET_VALUE, \
15249 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15250 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015251 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015252
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015253static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015254xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15255 xmlSchemaFacetPtr facet1,
15256 xmlSchemaFacetPtr facet2,
15257 int lessGreater,
15258 int orEqual,
15259 int ofBase)
15260{
15261 xmlChar *msg = NULL;
15262
15263 msg = xmlStrdup(BAD_CAST "'");
15264 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15265 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15266 if (lessGreater == 0)
15267 msg = xmlStrcat(msg, BAD_CAST " equal to");
15268 if (lessGreater == 1)
15269 msg = xmlStrcat(msg, BAD_CAST " greater than");
15270 else
15271 msg = xmlStrcat(msg, BAD_CAST " less than");
15272
15273 if (orEqual)
15274 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15275 msg = xmlStrcat(msg, BAD_CAST " '");
15276 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15277 if (ofBase)
15278 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15279 else
15280 msg = xmlStrcat(msg, BAD_CAST "'");
15281
15282 xmlSchemaPCustomErr(pctxt,
15283 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015284 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015285 (const char *) msg, NULL);
15286
15287 if (msg != NULL)
15288 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015289}
15290
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015291static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015292xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15293 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015294{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015295 xmlSchemaTypePtr base = type->baseType;
15296 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015297 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015298 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15299 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15300 fmininc = NULL, fmaxinc = NULL,
15301 fminexc = NULL, fmaxexc = NULL,
15302 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15303 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15304 bfmininc = NULL, bfmaxinc = NULL,
15305 bfminexc = NULL, bfmaxexc = NULL;
15306 int res, err = 0, fixedErr;
15307 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015308 * 3 The {facets} of R are the union of S and the {facets}
15309 * of B, eliminating duplicates. To eliminate duplicates,
15310 * when a facet of the same kind occurs in both S and the
15311 * {facets} of B, the one in the {facets} of B is not
15312 * included, with the exception of enumeration and pattern
15313 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015314 * are allowed.
15315 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015316
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015317 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15318 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015320 last = type->facetSet;
15321 if (last != NULL)
15322 while (last->next != NULL)
15323 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015324
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015325 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15326 facet = cur->facet;
15327 switch (facet->type) {
15328 case XML_SCHEMA_FACET_LENGTH:
15329 flength = facet; break;
15330 case XML_SCHEMA_FACET_MINLENGTH:
15331 fminlen = facet; break;
15332 case XML_SCHEMA_FACET_MININCLUSIVE:
15333 fmininc = facet; break;
15334 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15335 fminexc = facet; break;
15336 case XML_SCHEMA_FACET_MAXLENGTH:
15337 fmaxlen = facet; break;
15338 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15339 fmaxinc = facet; break;
15340 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15341 fmaxexc = facet; break;
15342 case XML_SCHEMA_FACET_TOTALDIGITS:
15343 ftotdig = facet; break;
15344 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15345 ffracdig = facet; break;
15346 default:
15347 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015348 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015349 }
15350 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15351 facet = cur->facet;
15352 switch (facet->type) {
15353 case XML_SCHEMA_FACET_LENGTH:
15354 bflength = facet; break;
15355 case XML_SCHEMA_FACET_MINLENGTH:
15356 bfminlen = facet; break;
15357 case XML_SCHEMA_FACET_MININCLUSIVE:
15358 bfmininc = facet; break;
15359 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15360 bfminexc = facet; break;
15361 case XML_SCHEMA_FACET_MAXLENGTH:
15362 bfmaxlen = facet; break;
15363 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15364 bfmaxinc = facet; break;
15365 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15366 bfmaxexc = facet; break;
15367 case XML_SCHEMA_FACET_TOTALDIGITS:
15368 bftotdig = facet; break;
15369 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15370 bffracdig = facet; break;
15371 default:
15372 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015373 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015374 }
15375 err = 0;
15376 /*
15377 * length and minLength or maxLength (2.2) + (3.2)
15378 */
15379 if (flength && (fminlen || fmaxlen)) {
15380 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15381 "either of 'minLength' or 'maxLength' to be specified on "
15382 "the same type definition")
15383 }
15384 /*
15385 * Mutual exclusions in the same derivation step.
15386 */
15387 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015388 /*
15389 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015390 */
15391 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15392 }
15393 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015394 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015395 * SCC "minInclusive and minExclusive"
15396 */
15397 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015398 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015399
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015400 if (flength && bflength) {
15401 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015402 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015403 * The values have to be equal.
15404 */
15405 res = xmlSchemaCompareValues(flength->val, bflength->val);
15406 if (res == -2)
15407 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015408 if (res != 0)
15409 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15410 if ((res != 0) && (bflength->fixed)) {
15411 FACET_RESTR_FIXED_ERR(flength)
15412 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015413
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015414 }
15415 if (fminlen && bfminlen) {
15416 /*
15417 * SCC "minLength valid restriction"
15418 * minLength >= BASE minLength
15419 */
15420 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15421 if (res == -2)
15422 goto internal_error;
15423 if (res == -1)
15424 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15425 if ((res != 0) && (bfminlen->fixed)) {
15426 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015427 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015428 }
15429 if (fmaxlen && bfmaxlen) {
15430 /*
15431 * SCC "maxLength valid restriction"
15432 * maxLength <= BASE minLength
15433 */
15434 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15435 if (res == -2)
15436 goto internal_error;
15437 if (res == 1)
15438 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15439 if ((res != 0) && (bfmaxlen->fixed)) {
15440 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015441 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015442 }
15443 /*
15444 * SCC "length and minLength or maxLength"
15445 */
15446 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015447 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015448 if (flength) {
15449 if (! fminlen)
15450 flength = bflength;
15451 if (fminlen) {
15452 /* (1.1) length >= minLength */
15453 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15454 if (res == -2)
15455 goto internal_error;
15456 if (res == -1)
15457 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15458 }
15459 if (! fmaxlen)
15460 fmaxlen = bfmaxlen;
15461 if (fmaxlen) {
15462 /* (2.1) length <= maxLength */
15463 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15464 if (res == -2)
15465 goto internal_error;
15466 if (res == 1)
15467 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15468 }
15469 }
15470 if (fmaxinc) {
15471 /*
15472 * "maxInclusive"
15473 */
15474 if (fmininc) {
15475 /* SCC "maxInclusive >= minInclusive" */
15476 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15477 if (res == -2)
15478 goto internal_error;
15479 if (res == -1) {
15480 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15481 }
15482 }
15483 /*
15484 * SCC "maxInclusive valid restriction"
15485 */
15486 if (bfmaxinc) {
15487 /* maxInclusive <= BASE maxInclusive */
15488 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15489 if (res == -2)
15490 goto internal_error;
15491 if (res == 1)
15492 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15493 if ((res != 0) && (bfmaxinc->fixed)) {
15494 FACET_RESTR_FIXED_ERR(fmaxinc)
15495 }
15496 }
15497 if (bfmaxexc) {
15498 /* maxInclusive < BASE maxExclusive */
15499 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15500 if (res == -2)
15501 goto internal_error;
15502 if (res != -1) {
15503 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15504 }
15505 }
15506 if (bfmininc) {
15507 /* maxInclusive >= BASE minInclusive */
15508 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15509 if (res == -2)
15510 goto internal_error;
15511 if (res == -1) {
15512 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15513 }
15514 }
15515 if (bfminexc) {
15516 /* maxInclusive > BASE minExclusive */
15517 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15518 if (res == -2)
15519 goto internal_error;
15520 if (res != 1) {
15521 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15522 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015523 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015524 }
15525 if (fmaxexc) {
15526 /*
15527 * "maxExclusive >= minExclusive"
15528 */
15529 if (fminexc) {
15530 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15531 if (res == -2)
15532 goto internal_error;
15533 if (res == -1) {
15534 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15535 }
15536 }
15537 /*
15538 * "maxExclusive valid restriction"
15539 */
15540 if (bfmaxexc) {
15541 /* maxExclusive <= BASE maxExclusive */
15542 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15543 if (res == -2)
15544 goto internal_error;
15545 if (res == 1) {
15546 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15547 }
15548 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015549 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015550 }
15551 }
15552 if (bfmaxinc) {
15553 /* maxExclusive <= BASE maxInclusive */
15554 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15555 if (res == -2)
15556 goto internal_error;
15557 if (res == 1) {
15558 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15559 }
15560 }
15561 if (bfmininc) {
15562 /* maxExclusive > BASE minInclusive */
15563 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15564 if (res == -2)
15565 goto internal_error;
15566 if (res != 1) {
15567 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15568 }
15569 }
15570 if (bfminexc) {
15571 /* maxExclusive > BASE minExclusive */
15572 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15573 if (res == -2)
15574 goto internal_error;
15575 if (res != 1) {
15576 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15577 }
15578 }
15579 }
15580 if (fminexc) {
15581 /*
15582 * "minExclusive < maxInclusive"
15583 */
15584 if (fmaxinc) {
15585 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15586 if (res == -2)
15587 goto internal_error;
15588 if (res != -1) {
15589 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15590 }
15591 }
15592 /*
15593 * "minExclusive valid restriction"
15594 */
15595 if (bfminexc) {
15596 /* minExclusive >= BASE minExclusive */
15597 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15598 if (res == -2)
15599 goto internal_error;
15600 if (res == -1) {
15601 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15602 }
15603 if ((res != 0) && (bfminexc->fixed)) {
15604 FACET_RESTR_FIXED_ERR(fminexc)
15605 }
15606 }
15607 if (bfmaxinc) {
15608 /* minExclusive <= BASE maxInclusive */
15609 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15610 if (res == -2)
15611 goto internal_error;
15612 if (res == 1) {
15613 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15614 }
15615 }
15616 if (bfmininc) {
15617 /* minExclusive >= BASE minInclusive */
15618 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15619 if (res == -2)
15620 goto internal_error;
15621 if (res == -1) {
15622 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15623 }
15624 }
15625 if (bfmaxexc) {
15626 /* minExclusive < BASE maxExclusive */
15627 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15628 if (res == -2)
15629 goto internal_error;
15630 if (res != -1) {
15631 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15632 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015633 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015634 }
15635 if (fmininc) {
15636 /*
15637 * "minInclusive < maxExclusive"
15638 */
15639 if (fmaxexc) {
15640 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15641 if (res == -2)
15642 goto internal_error;
15643 if (res != -1) {
15644 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15645 }
15646 }
15647 /*
15648 * "minExclusive valid restriction"
15649 */
15650 if (bfmininc) {
15651 /* minInclusive >= BASE minInclusive */
15652 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15653 if (res == -2)
15654 goto internal_error;
15655 if (res == -1) {
15656 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15657 }
15658 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015659 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015660 }
15661 }
15662 if (bfmaxinc) {
15663 /* minInclusive <= BASE maxInclusive */
15664 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15665 if (res == -2)
15666 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000015667 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015668 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15669 }
15670 }
15671 if (bfminexc) {
15672 /* minInclusive > BASE minExclusive */
15673 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15674 if (res == -2)
15675 goto internal_error;
15676 if (res != 1)
15677 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15678 }
15679 if (bfmaxexc) {
15680 /* minInclusive < BASE maxExclusive */
15681 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15682 if (res == -2)
15683 goto internal_error;
15684 if (res != -1)
15685 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15686 }
15687 }
15688 if (ftotdig && bftotdig) {
15689 /*
15690 * SCC " totalDigits valid restriction"
15691 * totalDigits <= BASE totalDigits
15692 */
15693 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15694 if (res == -2)
15695 goto internal_error;
15696 if (res == 1)
15697 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15698 -1, 1, 1);
15699 if ((res != 0) && (bftotdig->fixed)) {
15700 FACET_RESTR_FIXED_ERR(ftotdig)
15701 }
15702 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015703 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015704 /*
15705 * SCC "fractionDigits valid restriction"
15706 * fractionDigits <= BASE fractionDigits
15707 */
15708 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15709 if (res == -2)
15710 goto internal_error;
15711 if (res == 1)
15712 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15713 -1, 1, 1);
15714 if ((res != 0) && (bffracdig->fixed)) {
15715 FACET_RESTR_FIXED_ERR(ffracdig)
15716 }
15717 }
15718 /*
15719 * SCC "fractionDigits less than or equal to totalDigits"
15720 */
15721 if (! ftotdig)
15722 ftotdig = bftotdig;
15723 if (! ffracdig)
15724 ffracdig = bffracdig;
15725 if (ftotdig && ffracdig) {
15726 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15727 if (res == -2)
15728 goto internal_error;
15729 if (res == 1)
15730 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15731 -1, 1, 0);
15732 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015733 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015734 * *Enumerations* won' be added here, since only the first set
15735 * of enumerations in the ancestor-or-self axis is used
15736 * for validation, plus we need to use the base type of those
15737 * enumerations for whitespace.
15738 *
15739 * *Patterns*: won't be add here, since they are ORed at
15740 * type level and ANDed at ancestor level. This will
15741 * happed during validation by walking the base axis
15742 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015743 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015744 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15745 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015746 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015747 * Special handling of enumerations and patterns.
15748 * TODO: hmm, they should not appear in the set, so remove this.
15749 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015750 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015751 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015752 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015753 /*
15754 * Search for a duplicate facet in the current type.
15755 */
15756 link = type->facetSet;
15757 err = 0;
15758 fixedErr = 0;
15759 while (link != NULL) {
15760 facet = link->facet;
15761 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015762 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015763 case XML_SCHEMA_FACET_WHITESPACE:
15764 /*
15765 * The whitespace must be stronger.
15766 */
15767 if (facet->whitespace < bfacet->whitespace) {
15768 FACET_RESTR_ERR(flength,
15769 "The 'whitespace' value has to be equal to "
15770 "or stronger than the 'whitespace' value of "
15771 "the base type")
15772 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015773 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015774 (facet->whitespace != bfacet->whitespace)) {
15775 FACET_RESTR_FIXED_ERR(facet)
15776 }
15777 break;
15778 default:
15779 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015780 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015781 /* Duplicate found. */
15782 break;
15783 }
15784 link = link->next;
15785 }
15786 /*
15787 * If no duplicate was found: add the base types's facet
15788 * to the set.
15789 */
15790 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015791 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015792 xmlMalloc(sizeof(xmlSchemaFacetLink));
15793 if (link == NULL) {
15794 xmlSchemaPErrMemory(pctxt,
15795 "deriving facets, creating a facet link", NULL);
15796 return (-1);
15797 }
15798 link->facet = cur->facet;
15799 link->next = NULL;
15800 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015801 type->facetSet = link;
15802 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015803 last->next = link;
15804 last = link;
15805 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015806
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015807 }
15808
15809 return (0);
15810internal_error:
15811 xmlSchemaPCustomErr(pctxt,
15812 XML_SCHEMAP_INVALID_FACET_VALUE,
15813 NULL, type, NULL,
15814 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15815 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015816}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015817
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015818static int
15819xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15820 xmlSchemaTypePtr type)
15821{
15822 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15823 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015824 * The actual value is then formed by replacing any union type
15825 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015826 * {member type definitions}, in order.
15827 */
15828 link = type->memberTypes;
15829 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015830
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015831 if (IS_NOT_TYPEFIXED(link->type))
15832 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15833
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015834 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015835 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015836 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015837 link->type = subLink->type;
15838 if (subLink->next != NULL) {
15839 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015840 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015841 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015842 while (subLink != NULL) {
15843 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015844 xmlMalloc(sizeof(xmlSchemaTypeLink));
15845 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015846 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015847 NULL);
15848 return (-1);
15849 }
15850 newLink->type = subLink->type;
15851 prevLink->next = newLink;
15852 prevLink = newLink;
15853 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015854
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015855 subLink = subLink->next;
15856 }
15857 }
15858 }
15859 }
15860 link = link->next;
15861 }
15862 return (0);
15863}
15864
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015865static void
15866xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15867{
15868 int has = 0, needVal = 0, normVal = 0;
15869
15870 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15871 if (has) {
15872 needVal = (type->baseType->flags &
15873 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15874 normVal = (type->baseType->flags &
15875 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15876 }
15877 if (type->facets != NULL) {
15878 xmlSchemaFacetPtr fac;
15879
15880 for (fac = type->facets; fac != NULL; fac = fac->next) {
15881 switch (fac->type) {
15882 case XML_SCHEMA_FACET_WHITESPACE:
15883 break;
15884 case XML_SCHEMA_FACET_PATTERN:
15885 normVal = 1;
15886 has = 1;
15887 break;
15888 case XML_SCHEMA_FACET_ENUMERATION:
15889 needVal = 1;
15890 normVal = 1;
15891 has = 1;
15892 break;
15893 default:
15894 has = 1;
15895 break;
15896 }
15897 }
15898 }
15899 if (normVal)
15900 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15901 if (needVal)
15902 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15903 if (has)
15904 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15905
15906 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15907 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15908 /*
15909 * OPTIMIZE VAL TODO: Some facets need a computed value.
15910 */
15911 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15912 (prim->builtInType != XML_SCHEMAS_STRING)) {
15913 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15914 }
15915 }
15916}
15917
15918static int
15919xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15920{
15921
15922
15923 /*
15924 * Evaluate the whitespace-facet value.
15925 */
15926 if (VARIETY_LIST(type)) {
15927 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15928 return (0);
15929 } else if (VARIETY_UNION(type))
15930 return (0);
15931
15932 if (type->facetSet != NULL) {
15933 xmlSchemaFacetLinkPtr lin;
15934
15935 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15936 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15937 switch (lin->facet->whitespace) {
15938 case XML_SCHEMAS_FACET_PRESERVE:
15939 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15940 break;
15941 case XML_SCHEMAS_FACET_REPLACE:
15942 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15943 break;
15944 case XML_SCHEMAS_FACET_COLLAPSE:
15945 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15946 break;
15947 default:
15948 return (-1);
15949 }
15950 return (0);
15951 }
15952 }
15953 }
15954 /*
15955 * For all ·atomic· datatypes other than string (and types ·derived·
15956 * by ·restriction· from it) the value of whiteSpace is fixed to
15957 * collapse
15958 */
15959 {
15960 xmlSchemaTypePtr anc;
15961
15962 for (anc = type->baseType; anc != NULL &&
15963 anc->builtInType != XML_SCHEMAS_ANYTYPE;
15964 anc = anc->baseType) {
15965
15966 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
15967 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
15968 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15969
15970 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
15971 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
15972 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15973
15974 } else
15975 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15976 break;
15977 }
15978 }
15979 return (0);
15980 }
15981 return (0);
15982}
15983
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015984/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015985 * xmlSchemaTypeFixup:
15986 * @typeDecl: the schema type definition
15987 * @ctxt: the schema parser context
15988 *
15989 * Fixes the content model of the type.
15990 */
15991static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015992xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015993 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000015994{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015995 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000015996 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015997 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
15998 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000015999 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016000 if (! IS_NOT_TYPEFIXED(type))
16001 return;
16002 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016003 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016004 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016005
16006 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016007 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016008 XML_SCHEMAP_INTERNAL,
16009 NULL, type, NULL,
16010 "Internal error: xmlSchemaTypeFixup, "
16011 "baseType is missing on '%s'", type->name);
16012 return;
16013 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016014
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016015 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016016 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016017
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016018 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016019 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016020 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016021 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016022 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016023 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16024 /*
16025 * Skip fixup if the base type is invalid.
16026 * TODO: Generate a warning!
16027 */
16028 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016029 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016030 /*
16031 * This basically checks if the base type can be derived.
16032 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016033 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016034 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16035 return;
16036 }
16037 /*
16038 * Fixup the content type.
16039 */
16040 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16041 /*
16042 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016043 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016044 if ((IS_COMPLEX_TYPE(baseType)) &&
16045 (baseType->contentTypeDef != NULL) &&
16046 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016047 xmlSchemaTypePtr contentBase, content;
16048 char buf[30];
16049 const xmlChar *tmpname;
16050 /*
16051 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016052 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016053 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016054 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016055 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016056 * SPEC (1.1) "the simple type definition corresponding to the
16057 * <simpleType> among the [children] of <restriction> if there
16058 * is one;"
16059 * Note that this "<simpleType> among the [children]" was put
16060 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016061 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016062 contentBase = type->contentTypeDef;
16063 type->contentTypeDef = NULL;
16064 } else {
16065 /*
16066 * (1.2) "...otherwise (<restriction> has no <simpleType>
16067 * among its [children]), the simple type definition which
16068 * is the {content type} of the ... base type."
16069 */
16070 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016071 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016072 /*
16073 * SPEC
16074 * "... a simple type definition which restricts the simple
16075 * type definition identified in clause 1.1 or clause 1.2
16076 * with a set of facet components"
16077 *
16078 * Create the anonymous simple type, which will be the content
16079 * type of the complex type.
16080 */
16081 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16082 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16083 content = xmlSchemaAddType(pctxt,
16084 pctxt->schema, tmpname, tmpname, type->node);
16085 if (content == NULL)
16086 return;
16087 /*
16088 * We will use the same node as for the <complexType>
16089 * to have it somehow anchored in the schema doc.
16090 */
16091 content->node = type->node;
16092 content->type = XML_SCHEMA_TYPE_SIMPLE;
16093 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16094 content->baseType = contentBase;
16095 /*
16096 * Move the facets, previously anchored on the complexType.
16097 */
16098 content->facets = type->facets;
16099 type->facets = NULL;
16100 content->facetSet = type->facetSet;
16101 type->facetSet = NULL;
16102
16103 type->contentTypeDef = content;
16104 if (IS_NOT_TYPEFIXED(contentBase))
16105 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16106 xmlSchemaTypeFixup(content, pctxt, NULL);
16107
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016108 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16109 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16110 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16111 /*
16112 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16113 * an emptiable particle, then a simple type definition which
16114 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016115 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016116 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016117 (type->contentTypeDef->baseType == NULL)) {
16118 /*
16119 * TODO: Check if this ever happens.
16120 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016121 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016122 XML_SCHEMAP_INTERNAL,
16123 NULL, type, NULL,
16124 "Internal error: xmlSchemaTypeFixup, "
16125 "complex type '%s': the <simpleContent><restriction> "
16126 "is missing a <simpleType> child, but was not catched "
16127 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016128 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016129 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16130 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16131 /*
16132 * SPEC (3) If <extension> + base is <complexType> with
16133 * <simpleType> content, "...then the {content type} of that
16134 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016135 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016136 if (baseType->contentTypeDef == NULL) {
16137 /*
16138 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16139 * should have catched this already.
16140 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016141 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016142 XML_SCHEMAP_INTERNAL,
16143 NULL, type, NULL,
16144 "Internal error: xmlSchemaTypeFixup, "
16145 "complex type '%s': the <extension>ed base type is "
16146 "a complex type with no simple content type",
16147 type->name);
16148 }
16149 type->contentTypeDef = baseType->contentTypeDef;
16150 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16151 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16152 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016153 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016154 * "... then that simple type definition"
16155 */
16156 type->contentTypeDef = baseType;
16157 } else {
16158 /*
16159 * TODO: Check if this ever happens.
16160 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016161 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016162 XML_SCHEMAP_INTERNAL,
16163 NULL, type, NULL,
16164 "Internal error: xmlSchemaTypeFixup, "
16165 "complex type '%s' with <simpleContent>: unhandled "
16166 "derivation case", type->name);
16167 }
16168 } else {
16169 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016170 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016171 (xmlSchemaParticlePtr) type->subtypes;
16172 /*
16173 * Corresponds to <complexType><complexContent>...
16174 *
16175 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016176 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016177 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016178 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016179 * Compute the "effective content":
16180 * (2.1.1) + (2.1.2) + (2.1.3)
16181 */
16182 if ((particle == NULL) ||
16183 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16184 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16185 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16186 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16187 (particle->minOccurs == 0))) &&
16188 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016189 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016190 /*
16191 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16192 * a particle whose properties are as follows:..."
16193 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016194 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016195 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16196 * NOTE that we sill assign it the <complexType> node to
16197 * somehow anchor it in the doc.
16198 */
16199 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016200 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016201 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016202 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016203 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016204 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016205 type->node, 1, 1);
16206 if (particle == NULL)
16207 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016208 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016209 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016210 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016211 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016212 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016213 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16214 if (particle->children == NULL)
16215 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016216
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016217 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016218 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016219 dummySequence = 1;
16220 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16221 } else {
16222 /*
16223 * SPEC (2.1.5) "otherwise empty"
16224 */
16225 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016226 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016227 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016228 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016229 * SPEC (2.2) "otherwise the particle corresponding to the
16230 * <all>, <choice>, <group> or <sequence> among the
16231 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016232 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016233 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16234 }
16235 /*
16236 * Compute the "content type".
16237 */
16238 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016239 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016240 * SPEC (3.1) "If <restriction>..."
16241 * (3.1.1) + (3.1.2) */
16242 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16243 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16244 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16245 }
16246 } else {
16247 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016248 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016249 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016250 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16251 /*
16252 * SPEC (3.2.1)
16253 */
16254 type->contentType = baseType->contentType;
16255 type->subtypes = baseType->subtypes;
16256 /*
16257 * NOTE that the effective mixed is ignored here.
16258 */
16259 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16260 /*
16261 * SPEC (3.2.2)
16262 */
16263 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16264 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16265 } else {
16266 /*
16267 * SPEC (3.2.3)
16268 */
16269 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16270 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16271 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016272 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016273 * {particles} are..."
16274 */
16275 if (! dummySequence) {
16276 xmlSchemaTreeItemPtr effectiveContent =
16277 (xmlSchemaTreeItemPtr) type->subtypes;
16278 /*
16279 * Create the particle.
16280 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016281 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016282 type->node, 1, 1);
16283 if (particle == NULL)
16284 return;
16285 /*
16286 * Create the "sequence" model group.
16287 */
16288 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016289 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016290 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16291 if (particle->children == NULL)
16292 return;
16293 type->subtypes = (xmlSchemaTypePtr) particle;
16294 /*
16295 * SPEC "the particle of the {content type} of
16296 * the ... base ..."
16297 * Create a duplicate of the base type's particle
16298 * and assign its "term" to it.
16299 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016300 particle->children->children =
16301 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16302 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016303 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016304 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016305 if (particle->children->children == NULL)
16306 return;
16307 particle = (xmlSchemaParticlePtr)
16308 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016309 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016310 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16311 /*
16312 * SPEC "followed by the ·effective content·."
16313 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016314 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016315 } else {
16316 /*
16317 * This is the case when there is already an empty
16318 * <sequence> with minOccurs==maxOccurs==1.
16319 * Just add the base types's content type.
16320 * NOTE that, although we miss to add an intermediate
16321 * <sequence>, this should produce no difference to
16322 * neither the regex compilation of the content model,
16323 * nor to the complex type contraints.
16324 */
16325 particle->children->children =
16326 (xmlSchemaTreeItemPtr) baseType->subtypes;
16327 }
16328 }
16329 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016330 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016331 /*
16332 * Apply the complex type component constraints; this will not
16333 * check attributes, since this is done in
16334 * xmlSchemaBuildAttributeValidation().
16335 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016336 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16337 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016338 /*
16339 * Inherit & check constraints for attributes.
16340 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016341 xmlSchemaBuildAttributeValidation(pctxt, type);
16342 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016343 /*
16344 * Simple Type Definition Schema Component
16345 */
16346 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016347 if (VARIETY_LIST(type)) {
16348 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016349 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016350 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016351 if (type->subtypes == NULL) {
16352 /*
16353 * This one is really needed, so get out.
16354 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016355 PERROR_INT("xmlSchemaTypeFixup",
16356 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016357 return;
16358 }
16359 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016360 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16361 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016362 /*
16363 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016364 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016365 if (type->memberTypes == NULL) {
16366 /*
16367 * This one is really needed, so get out.
16368 */
16369 return;
16370 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016371 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016372 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016373 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016374 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016375 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016376 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016377 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016378 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016379 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16380 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016381 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016382 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016383 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016384 */
16385 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016386 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016387 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016388 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16389 /*
16390 * Inherit the itemType.
16391 */
16392 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016393 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016394 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16395 /*
16396 * NOTE that we won't assign the memberTypes of the base,
16397 * since this will make trouble when freeing them; we will
16398 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016399 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016400 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016401 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016402 /*
16403 * Check constraints.
16404 *
16405 * TODO: Split this somehow, we need to know first if we can derive
16406 * from the base type at all!
16407 */
16408 if (type->baseType != NULL) {
16409 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016410 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016411 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016412 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016413 * applied beforehand.
16414 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016415 xmlSchemaCheckSRCSimpleType(pctxt, type);
16416 xmlSchemaCheckFacetValues(type, pctxt);
16417 if ((type->facetSet != NULL) ||
16418 (type->baseType->facetSet != NULL))
16419 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16420 /*
16421 * Whitespace value.
16422 */
16423 xmlSchemaTypeFixupWhitespace(type);
16424 xmlSchemaTypeFixupOptimFacets(type);
16425 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016426 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016427
Daniel Veillard8651f532002-04-17 09:06:27 +000016428#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016429 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016430 xmlGenericError(xmlGenericErrorContext,
16431 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016432 type->node->doc->URL,
16433 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016434 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016435 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016436 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016437 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16438 switch (type->contentType) {
16439 case XML_SCHEMA_CONTENT_SIMPLE:
16440 xmlGenericError(xmlGenericErrorContext, "simple\n");
16441 break;
16442 case XML_SCHEMA_CONTENT_ELEMENTS:
16443 xmlGenericError(xmlGenericErrorContext, "elements\n");
16444 break;
16445 case XML_SCHEMA_CONTENT_UNKNOWN:
16446 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16447 break;
16448 case XML_SCHEMA_CONTENT_EMPTY:
16449 xmlGenericError(xmlGenericErrorContext, "empty\n");
16450 break;
16451 case XML_SCHEMA_CONTENT_MIXED:
16452 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016453 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016454 xmlGenericError(xmlGenericErrorContext,
16455 "mixed as emptiable particle\n");
16456 else
16457 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16458 break;
16459 /* Removed, since not used. */
16460 /*
16461 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16462 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16463 break;
16464 */
16465 case XML_SCHEMA_CONTENT_BASIC:
16466 xmlGenericError(xmlGenericErrorContext, "basic\n");
16467 break;
16468 default:
16469 xmlGenericError(xmlGenericErrorContext,
16470 "not registered !!!\n");
16471 break;
16472 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016473 }
16474#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016475}
16476
16477/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016478 * xmlSchemaCheckFacet:
16479 * @facet: the facet
16480 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016481 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016482 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016483 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016484 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016485 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016486 * Returns 0 if valid, a positive error code if not valid and
16487 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016488 */
16489int
16490xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016491 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016492 xmlSchemaParserCtxtPtr pctxt,
16493 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016494{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016495 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016496
Daniel Veillardce682bc2004-11-05 17:22:25 +000016497 if ((facet == NULL) || (typeDecl == NULL))
16498 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016499 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016500 * TODO: will the parser context be given if used from
16501 * the relaxNG module?
16502 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016503 if (pctxt == NULL)
16504 ctxtGiven = 0;
16505 else
16506 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016507
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016508 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016509 case XML_SCHEMA_FACET_MININCLUSIVE:
16510 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16511 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016512 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16513 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016514 /*
16515 * Okay we need to validate the value
16516 * at that point.
16517 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016518 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016519
16520 /* 4.3.5.5 Constraints on enumeration Schema Components
16521 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016522 * It is an ·error· if any member of {value} is not in the
16523 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016524 *
16525 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016526 * The value ·must· be in the
16527 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016528 */
16529 /*
16530 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016531 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016532 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016533 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016534 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016535 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016536 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016537 */
16538 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16539 base = typeDecl->baseType;
16540 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016541 PERROR_INT("xmlSchemaCheckFacet",
16542 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016543 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016544 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016545 } else
16546 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016547
16548 if (! ctxtGiven) {
16549 /*
16550 * A context is needed if called from RelaxNG.
16551 */
16552 pctxt = xmlSchemaNewParserCtxt("*");
16553 if (pctxt == NULL)
16554 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016555 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016556 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016557 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016558 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016559 * facet->node is just the node holding the facet
16560 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016561 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016562 */
16563 ret = xmlSchemaVCheckCVCSimpleType(
16564 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16565 facet->value, &(facet->val), 1, 1, 0);
16566 if (ret != 0) {
16567 if (ret < 0) {
16568 /* No error message for RelaxNG. */
16569 if (ctxtGiven) {
16570 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16571 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16572 "Internal error: xmlSchemaCheckFacet, "
16573 "failed to validate the value '%s' of the "
16574 "facet '%s' against the base type",
16575 facet->value, xmlSchemaFacetTypeToString(facet->type));
16576 }
16577 goto internal_error;
16578 }
16579 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16580 /* No error message for RelaxNG. */
16581 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016582 xmlChar *str = NULL;
16583
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016584 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16585 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016586 "The value '%s' of the facet does not validate "
16587 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016588 facet->value,
16589 xmlSchemaFormatQName(&str,
16590 base->targetNamespace, base->name));
16591 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016592 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016593 goto exit;
16594 } else if (facet->val == NULL) {
16595 if (ctxtGiven) {
16596 PERROR_INT("xmlSchemaCheckFacet",
16597 "value was not computed");
16598 }
16599 TODO
16600 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016601 break;
16602 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016603 case XML_SCHEMA_FACET_PATTERN:
16604 facet->regexp = xmlRegexpCompile(facet->value);
16605 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016606 ret = XML_SCHEMAP_REGEXP_INVALID;
16607 /* No error message for RelaxNG. */
16608 if (ctxtGiven) {
16609 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16610 ret, facet->node, typeDecl,
16611 "The value '%s' of the facet 'pattern' is not a "
16612 "valid regular expression",
16613 facet->value, NULL);
16614 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016615 }
16616 break;
16617 case XML_SCHEMA_FACET_TOTALDIGITS:
16618 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16619 case XML_SCHEMA_FACET_LENGTH:
16620 case XML_SCHEMA_FACET_MAXLENGTH:
16621 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016622 ret = xmlSchemaValidatePredefinedType(
16623 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16624 facet->value, &(facet->val));
16625 if (ret != 0) {
16626 if (ret < 0) {
16627 /* No error message for RelaxNG. */
16628 if (ctxtGiven) {
16629 PERROR_INT("xmlSchemaCheckFacet",
16630 "validating facet value");
16631 }
16632 goto internal_error;
16633 }
16634 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16635 /* No error message for RelaxNG. */
16636 if (ctxtGiven) {
16637 /* error code */
16638 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16639 ret, facet->node, typeDecl,
16640 "The value '%s' of the facet '%s' is not a valid "
16641 "'nonNegativeInteger'",
16642 facet->value,
16643 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016644 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016645 }
16646 break;
16647 }
16648 case XML_SCHEMA_FACET_WHITESPACE:{
16649 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16650 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16651 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16652 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16653 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16654 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16655 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016656 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16657 /* No error message for RelaxNG. */
16658 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016659 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016660 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16661 ret, facet->node, typeDecl,
16662 "The value '%s' of the facet 'whitespace' is not "
16663 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016664 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016665 }
16666 }
16667 default:
16668 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016669 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016670exit:
16671 if ((! ctxtGiven) && (pctxt != NULL))
16672 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016673 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016674internal_error:
16675 if ((! ctxtGiven) && (pctxt != NULL))
16676 xmlSchemaFreeParserCtxt(pctxt);
16677 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016678}
16679
16680/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016681 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016682 * @typeDecl: the schema type definition
16683 * @ctxt: the schema parser context
16684 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016685 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016686 */
16687static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016688xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16689 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016690{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016691 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016692 /*
16693 * NOTE: It is intended to use the facets list, instead
16694 * of facetSet.
16695 */
16696 if (typeDecl->facets != NULL) {
16697 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016698
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016699 /*
16700 * Temporarily assign the "schema" to the validation context
16701 * of the parser context. This is needed for NOTATION validation.
16702 */
16703 if (ctxt->vctxt == NULL) {
16704 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16705 return;
16706 }
16707 ctxt->vctxt->schema = ctxt->schema;
16708
Daniel Veillard01fa6152004-06-29 17:04:39 +000016709 while (facet != NULL) {
16710 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16711 facet = facet->next;
16712 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016713
16714 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016715 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016716}
16717
16718/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016719 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016720 * @ctxtMGroup: the searched model group
16721 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016722 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016723 *
16724 * This one is intended to be used by
16725 * xmlSchemaCheckGroupDefCircular only.
16726 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016727 * Returns the particle with the circular model group definition reference,
16728 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016729 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016730static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016731xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016732 xmlSchemaTreeItemPtr particle)
16733{
16734 xmlSchemaTreeItemPtr circ = NULL;
16735 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016736 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016737
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016738 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016739 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016740 if (term == NULL)
16741 continue;
16742 switch (term->type) {
16743 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016744 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016745 if (gdef == groupDef)
16746 return (particle);
16747 /*
16748 * Mark this model group definition to avoid infinite
16749 * recursion on circular references not yet examined.
16750 */
16751 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16752 continue;
16753 if (gdef->children != NULL) {
16754 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16755 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16756 gdef->children->children);
16757 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16758 if (circ != NULL)
16759 return (circ);
16760 }
16761 break;
16762 case XML_SCHEMA_TYPE_SEQUENCE:
16763 case XML_SCHEMA_TYPE_CHOICE:
16764 case XML_SCHEMA_TYPE_ALL:
16765 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16766 if (circ != NULL)
16767 return (circ);
16768 break;
16769 default:
16770 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016771 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016772 }
16773 return (NULL);
16774}
16775
16776/**
16777 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016778 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016779 * @ctxt: the parser context
16780 * @name: the name
16781 *
16782 * Checks for circular references to model group definitions.
16783 */
16784static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016785xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016786 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016787 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016788{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016789 /*
16790 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016791 * 2 Circular groups are disallowed. That is, within the {particles}
16792 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016793 * is the group itself.
16794 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016795 if ((item == NULL) ||
16796 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16797 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016798 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016799 {
16800 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016801
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016802 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016803 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016804 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016805 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016806 * TODO: The error report is not adequate: this constraint
16807 * is defined for model groups but not definitions, but since
16808 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016809 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016810 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016811 */
16812 xmlSchemaPCustomErr(ctxt,
16813 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016814 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016815 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016816 "defined", xmlSchemaFormatQName(&str,
16817 item->targetNamespace, item->name));
16818 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016819 /*
16820 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016821 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016822 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016823 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016824 }
16825 }
16826}
16827
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016828/**
16829 * xmlSchemaGroupDefTermFixup:
16830 * @item: the particle with a model group definition as term
16831 * @ctxt: the parser context
16832 * @name: the name
16833 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016834 * Checks cos-all-limited.
16835 *
16836 * Assigns the model group of model group definitions to the "term"
16837 * of the referencing particle.
16838 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16839 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016840 */
16841static void
16842xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016843 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016844 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016845{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016846 if ((item == NULL) ||
16847 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16848 (item->children == NULL) ||
16849 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16850 (item->children->children == NULL))
16851 return;
16852 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016853 /*
16854 * TODO: Not nice, but we will anchor cos-all-limited here.
16855 */
16856 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16857 (item->maxOccurs != 1)) {
16858 /*
16859 * SPEC (1.2) "the {term} property of a particle with
16860 * {max occurs}=1which is part of a pair which constitutes the
16861 * {content type} of a complex type definition."
16862 */
16863 xmlSchemaPCustomErr(ctxt,
16864 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16865 NULL, (xmlSchemaTypePtr) item, item->node,
16866 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16867 "group is its term", NULL);
16868 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016869}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016870
16871/**
16872 * xmlSchemaGetCircAttrGrRef:
16873 * @ctxtGr: the searched attribute group
16874 * @attr: the current attribute list to be processed
16875 *
16876 * This one is intended to be used by
16877 * xmlSchemaCheckSRCAttributeGroupCircular only.
16878 *
16879 * Returns the circular attribute grou reference, otherwise NULL.
16880 */
16881static xmlSchemaAttributeGroupPtr
16882xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16883 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016884{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016885 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16886 int marked;
16887 /*
16888 * We will search for an attribute group reference which
16889 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016890 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016891 while (attr != NULL) {
16892 marked = 0;
16893 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16894 gr = (xmlSchemaAttributeGroupPtr) attr;
16895 if (gr->refItem != NULL) {
16896 if (gr->refItem == ctxtGr)
16897 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016898 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016899 XML_SCHEMAS_ATTRGROUP_MARKED) {
16900 attr = attr->next;
16901 continue;
16902 } else {
16903 /*
16904 * Mark as visited to avoid infinite recursion on
16905 * circular references not yet examined.
16906 */
16907 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16908 marked = 1;
16909 }
16910 }
16911 if (gr->attributes != NULL)
16912 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16913 /*
16914 * Unmark the visited group's attributes.
16915 */
16916 if (marked)
16917 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16918 if (circ != NULL)
16919 return (circ);
16920 }
16921 attr = attr->next;
16922 }
16923 return (NULL);
16924}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016925
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016926/**
16927 * xmlSchemaCheckSRCAttributeGroupCircular:
16928 * attrGr: the attribute group definition
16929 * @ctxt: the parser context
16930 * @name: the name
16931 *
16932 * Checks for circular references of attribute groups.
16933 */
16934static void
16935xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016936 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016937 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016938{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016939 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016940 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016941 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016942 * 3 Circular group reference is disallowed outside <redefine>.
16943 * That is, unless this element information item's parent is
16944 * <redefine>, then among the [children], if any, there must
16945 * not be an <attributeGroup> with ref [attribute] which resolves
16946 * to the component corresponding to this <attributeGroup>. Indirect
16947 * circularity is also ruled out. That is, when QName resolution
16948 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16949 * any <attributeGroup>s with a ref [attribute] among the [children],
16950 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016951 * which resolves to the component corresponding to this <attributeGroup>.
16952 */
16953 /*
16954 * Only global components can be referenced.
16955 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016956 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016957 (attrGr->attributes == NULL))
16958 return;
16959 else {
16960 xmlSchemaAttributeGroupPtr circ;
16961
16962 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
16963 if (circ != NULL) {
16964 /*
16965 * TODO: Report the referenced attr group as QName.
16966 */
16967 xmlSchemaPCustomErr(ctxt,
16968 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16969 NULL, NULL, circ->node,
16970 "Circular reference to the attribute group '%s' "
16971 "defined", attrGr->name);
16972 /*
16973 * NOTE: We will cut the reference to avoid further
16974 * confusion of the processor.
16975 * BADSPEC: The spec should define how to process in this case.
16976 */
16977 circ->attributes = NULL;
16978 circ->refItem = NULL;
16979 }
16980 }
16981}
16982
16983/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000016984 * xmlSchemaAttrGrpFixup:
16985 * @attrgrpDecl: the schema attribute definition
16986 * @ctxt: the schema parser context
16987 * @name: the attribute name
16988 *
16989 * Fixes finish doing the computations on the attributes definitions
16990 */
16991static void
Daniel Veillard3646d642004-06-02 19:19:14 +000016992xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016993 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000016994{
16995 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000016996 name = attrgrp->name;
16997 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016998 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000016999 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017000 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017001
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017002 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017003 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017004 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017005 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017006 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017007 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17008 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017009 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017010 return;
17011 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017012 attrgrp->refItem = ref;
17013 /*
17014 * Check for self reference!
17015 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017016 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017017 attrgrp->attributes = ref->attributes;
17018 attrgrp->attributeWildcard = ref->attributeWildcard;
17019 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017020}
17021
17022/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017023 * xmlSchemaAttrCheckValConstr:
17024 * @item: an schema attribute declaration/use
17025 * @ctxt: a schema parser context
17026 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017027 *
17028 *
17029 * Schema Component Constraint: Attribute Declaration Properties Correct
17030 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017031 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017032 *
17033 * Fixes finish doing the computations on the attributes definitions
17034 */
17035static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017036xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017037 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017038 const xmlChar * name ATTRIBUTE_UNUSED)
17039{
17040
17041 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017042 * 2 if there is a {value constraint}, the canonical lexical
17043 * representation of its value must be ·valid· with respect
17044 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017045 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017046 if (item->defValue != NULL) {
17047 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017048
17049 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017050 PERROR_INT("xmlSchemaCheckAttrValConstr",
17051 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017052 return;
17053 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017054 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17055 item->node, item->subtypes, item->defValue, &(item->defVal),
17056 1, 1, 0);
17057 if (ret != 0) {
17058 if (ret < 0) {
17059 PERROR_INT("xmlSchemaAttrCheckValConstr",
17060 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017061 return;
17062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017063 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17064 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17065 ret, item->node, (xmlSchemaTypePtr) item,
17066 "The value of the value constraint is not valid", NULL, NULL);
17067 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017068 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017069 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017070}
17071
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017072static xmlSchemaElementPtr
17073xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17074 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017075{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017076 xmlSchemaElementPtr ret;
17077
17078 if (SUBST_GROUP_AFF(ancestor) == NULL)
17079 return (NULL);
17080 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17081 return (ancestor);
17082
17083 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17084 return (NULL);
17085 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17086 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17087 SUBST_GROUP_AFF(ancestor));
17088 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17089
17090 return (ret);
17091}
17092
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017093/**
17094 * xmlSchemaCheckElemPropsCorrect:
17095 * @ctxt: a schema parser context
17096 * @decl: the element declaration
17097 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017098 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017099 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017100 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017101 *
17102 * STATUS:
17103 * missing: (6)
17104 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017105static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017106xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17107 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017108{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017109 int ret = 0;
17110 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017111 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017112 * SPEC (1) "The values of the properties of an element declaration
17113 * must be as described in the property tableau in The Element
17114 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17115 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017116 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017117 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017118 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017119
17120 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017121 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017122 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017123 * affiliation}, then {scope} must be global."
17124 */
17125 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17126 xmlSchemaPCustomErr(pctxt,
17127 XML_SCHEMAP_E_PROPS_CORRECT_3,
17128 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17129 "Only global element declarations can have a "
17130 "substitution group affiliation", NULL);
17131 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017132 }
17133 /*
17134 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17135 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017136 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017137 * property."
17138 */
17139 if (head == elemDecl)
17140 circ = head;
17141 else if (SUBST_GROUP_AFF(head) != NULL)
17142 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17143 else
17144 circ = NULL;
17145 if (circ != NULL) {
17146 xmlChar *strA = NULL, *strB = NULL;
17147
17148 xmlSchemaPCustomErrExt(pctxt,
17149 XML_SCHEMAP_E_PROPS_CORRECT_6,
17150 NULL, (xmlSchemaTypePtr) circ, circ->node,
17151 "The element declaration '%s' defines a circular "
17152 "substitution group to element declaration '%s'",
17153 xmlSchemaGetComponentQName(&strA, circ),
17154 xmlSchemaGetComponentQName(&strB, head),
17155 NULL);
17156 FREE_AND_NULL(strA)
17157 FREE_AND_NULL(strB)
17158 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17159 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017160 /*
17161 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017162 * the {type definition}
17163 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017164 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017165 * of the {substitution group exclusions} of the {substitution group
17166 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17167 * (if the {type definition} is complex) or as defined in
17168 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017169 * simple)."
17170 *
17171 * NOTE: {substitution group exclusions} means the values of the
17172 * attribute "final".
17173 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017174
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017175 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017176 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017177
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017178 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17179 set |= SUBSET_EXTENSION;
17180 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17181 set |= SUBSET_RESTRICTION;
17182
17183 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17184 ELEM_TYPE(head), set) != 0) {
17185 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17186
17187 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017188 xmlSchemaPCustomErrExt(pctxt,
17189 XML_SCHEMAP_E_PROPS_CORRECT_4,
17190 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017191 "The type definition '%s' was "
17192 "either rejected by the substitution group "
17193 "affiliation '%s', or not validly derived from its type "
17194 "definition '%s'",
17195 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017196 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017197 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017198 FREE_AND_NULL(strA)
17199 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017200 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017201 }
17202 }
17203 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017204 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017205 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017206 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017207 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017208 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017209 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017210 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017211 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017212 ((IS_SIMPLE_TYPE(typeDef) &&
17213 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017214 (IS_COMPLEX_TYPE(typeDef) &&
17215 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017216 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17217 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017218
17219 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17220 xmlSchemaPCustomErr(pctxt,
17221 XML_SCHEMAP_E_PROPS_CORRECT_5,
17222 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17223 "The type definition (or type definition's content type) is or "
17224 "is derived from ID; value constraints are not allowed in "
17225 "conjunction with such a type definition", NULL);
17226 } else if (elemDecl->value != NULL) {
17227 int vcret;
17228 xmlNodePtr node = NULL;
17229
17230 /*
17231 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17232 * representation of its value must be ·valid· with respect to the
17233 * {type definition} as defined in Element Default Valid (Immediate)
17234 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017235 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017236 if (typeDef == NULL) {
17237 xmlSchemaPErr(pctxt, elemDecl->node,
17238 XML_SCHEMAP_INTERNAL,
17239 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17240 "type is missing... skipping validation of "
17241 "the value constraint", NULL, NULL);
17242 return (-1);
17243 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017244 if (elemDecl->node != NULL) {
17245 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17246 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17247 BAD_CAST "fixed");
17248 else
17249 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17250 BAD_CAST "default");
17251 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017252 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17253 typeDef, elemDecl->value, &(elemDecl->defVal));
17254 if (vcret != 0) {
17255 if (vcret < 0) {
17256 PERROR_INT("xmlSchemaElemCheckValConstr",
17257 "failed to validate the value constraint of an "
17258 "element declaration");
17259 return (-1);
17260 }
17261 return (vcret);
17262 }
17263 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017264
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017265 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017266}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017267
17268/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017269 * xmlSchemaCheckElemSubstGroup:
17270 * @ctxt: a schema parser context
17271 * @decl: the element declaration
17272 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017273 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017274 * Schema Component Constraint:
17275 * Substitution Group (cos-equiv-class)
17276 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017277 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017278 * a list will be built for each subst. group head, holding all direct
17279 * referents to this head.
17280 * NOTE that this function needs:
17281 * 1. circular subst. groups to be checked beforehand
17282 * 2. the declaration's type to be derived from the head's type
17283 *
17284 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017285 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017286 */
17287static void
17288xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17289 xmlSchemaElementPtr elemDecl)
17290{
17291 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17292 /* SPEC (1) "Its {abstract} is false." */
17293 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17294 return;
17295 {
17296 xmlSchemaElementPtr head;
17297 xmlSchemaTypePtr headType, type;
17298 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017299 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017300 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17301 * {disallowed substitutions} as the blocking constraint, as defined in
17302 * Substitution Group OK (Transitive) (§3.3.6)."
17303 */
17304 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17305 head = SUBST_GROUP_AFF(head)) {
17306 set = 0;
17307 methSet = 0;
17308 /*
17309 * The blocking constraints.
17310 */
17311 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17312 continue;
17313 headType = head->subtypes;
17314 type = elemDecl->subtypes;
17315 if (headType == type)
17316 goto add_member;
17317 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17318 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17319 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17320 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17321 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017322 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017323 * "The set of all {derivation method}s involved in the
17324 * derivation of D's {type definition} from C's {type definition}
17325 * does not intersect with the union of the blocking constraint,
17326 * C's {prohibited substitutions} (if C is complex, otherwise the
17327 * empty set) and the {prohibited substitutions} (respectively the
17328 * empty set) of any intermediate {type definition}s in the
17329 * derivation of D's {type definition} from C's {type definition}."
17330 */
17331 /*
17332 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17333 * subst.head axis, the methSet does not need to be computed for
17334 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017335 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017336 /*
17337 * The set of all {derivation method}s involved in the derivation
17338 */
17339 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017340 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017341 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17342 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17343 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017344
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017345 if ((type->flags &
17346 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17347 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17348 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17349
17350 type = type->baseType;
17351 }
17352 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017353 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017354 * the head's type.
17355 */
17356 type = elemDecl->subtypes->baseType;
17357 while (type != NULL) {
17358 if (IS_COMPLEX_TYPE(type)) {
17359 if ((type->flags &
17360 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17361 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17362 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17363 if ((type->flags &
17364 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17365 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17366 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17367 } else
17368 break;
17369 if (type == headType)
17370 break;
17371 type = type->baseType;
17372 }
17373 if ((set != 0) &&
17374 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17375 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17376 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17377 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17378 continue;
17379 }
17380add_member:
17381 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17382 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17383 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17384 }
17385 }
17386}
17387
17388/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017389 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017390 * @item: an schema element declaration/particle
17391 * @ctxt: a schema parser context
17392 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017393 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017394 * Validates the value constraints of an element declaration.
17395 *
17396 * Fixes finish doing the computations on the element declarations.
17397 */
17398static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017399xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017400 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017401 const xmlChar * name ATTRIBUTE_UNUSED)
17402{
17403 if (elemDecl == NULL)
17404 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017405 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17406 return;
17407 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017408 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17409 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017410}
17411
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017412/**
17413 * xmlSchemaMiscRefFixup:
17414 * @item: an schema component
17415 * @ctxt: a schema parser context
17416 * @name: the internal name of the component
17417 *
17418 * Resolves references of misc. schema components.
17419 */
17420static void
17421xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017422 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017423 const xmlChar * name ATTRIBUTE_UNUSED)
17424{
17425 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017426 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017427 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17428 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17429 xmlSchemaTreeItemPtr refItem;
17430 /*
17431 * Resolve the reference.
17432 */
17433 item->children = NULL;
17434 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17435 ref->itemType, ref->name, ref->targetNamespace);
17436 if (refItem == NULL) {
17437 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017438 NULL, GET_NODE(item), "ref", ref->name,
17439 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017440 } else {
17441 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17442 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017443 * NOTE that we will assign the model group definition
17444 * itself to the "term" of the particle. This will ease
17445 * the check for circular model group definitions. After
17446 * that the "term" will be assigned the model group of the
17447 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017448 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017449 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017450 } else
17451 item->children = refItem;
17452 }
17453 }
17454 }
17455}
17456
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017457static int
17458xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17459 xmlSchemaValPtr y)
17460{
17461 xmlSchemaTypePtr tx, ty, ptx, pty;
17462 int ret;
17463
17464 while (x != NULL) {
17465 /* Same types. */
17466 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17467 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17468 ptx = xmlSchemaGetPrimitiveType(tx);
17469 pty = xmlSchemaGetPrimitiveType(ty);
17470 /*
17471 * (1) if a datatype T' is ·derived· by ·restriction· from an
17472 * atomic datatype T then the ·value space· of T' is a subset of
17473 * the ·value space· of T. */
17474 /*
17475 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17476 * from a common atomic ancestor T then the ·value space·s of T'
17477 * and T'' may overlap.
17478 */
17479 if (ptx != pty)
17480 return(0);
17481 /*
17482 * We assume computed values to be normalized, so do a fast
17483 * string comparison for string based types.
17484 */
17485 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17486 IS_ANY_SIMPLE_TYPE(ptx)) {
17487 if (! xmlStrEqual(
17488 xmlSchemaValueGetAsString(x),
17489 xmlSchemaValueGetAsString(y)))
17490 return (0);
17491 } else {
17492 ret = xmlSchemaCompareValuesWhtsp(
17493 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17494 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17495 if (ret == -2)
17496 return(-1);
17497 if (ret != 0)
17498 return(0);
17499 }
17500 /*
17501 * Lists.
17502 */
17503 x = xmlSchemaValueGetNext(x);
17504 if (x != NULL) {
17505 y = xmlSchemaValueGetNext(y);
17506 if (y == NULL)
17507 return (0);
17508 } else if (xmlSchemaValueGetNext(y) != NULL)
17509 return (0);
17510 else
17511 return (1);
17512 }
17513 return (0);
17514}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017515
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017516/**
17517 * xmlSchemaAttrFixup:
17518 * @item: an schema attribute declaration/use.
17519 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017520 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017521 *
17522 * Fixes finish doing the computations on attribute declarations/uses.
17523 */
17524static void
17525xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017526 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017527 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017528{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017529 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017530 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017531 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017532 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017533 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017534 * The simple type definition corresponding to the <simpleType> element
17535 * information item in the [children], if present, otherwise the simple
17536 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017537 * [attribute], if present, otherwise the ·simple ur-type definition·.
17538 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017539 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017540 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017541 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17542 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017543 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017544 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017545 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017546
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017547 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17548 item->typeNs);
17549 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017550 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017551 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017552 (xmlSchemaTypePtr) item, item->node,
17553 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017554 XML_SCHEMA_TYPE_SIMPLE, NULL);
17555 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017556 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017557
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017558 } else if (item->ref != NULL) {
17559 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017560
Daniel Veillardc0826a72004-08-10 14:17:33 +000017561 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017562 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017563 * attribute declaration.
17564 */
17565 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017566 * TODO: Evaluate, what errors could occur if the declaration is not
17567 * found. It might be possible that the "typefixup" might crash if
17568 * no ref declaration was found.
17569 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017570 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017571 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017572 xmlSchemaPResCompAttrErr(ctxt,
17573 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017574 (xmlSchemaTypePtr) item, item->node,
17575 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017576 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017577 return;
17578 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017579 item->refDecl = decl;
17580 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017581 item->subtypes = decl->subtypes;
17582 /*
17583 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017584 * au-props-correct.2: If the {attribute declaration} has a fixed
17585 * {value constraint}, then if the attribute use itself has a
17586 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017587 * that of the {attribute declaration}'s {value constraint}.
17588 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017589 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017590 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017591 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017592 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017593 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17594 NULL, NULL, item->node,
17595 "The attribute declaration has a 'fixed' value constraint "
17596 ", thus it must be 'fixed' in attribute use as well",
17597 NULL);
17598 } else {
17599 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17600 xmlSchemaPCustomErr(ctxt,
17601 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17602 NULL, NULL, item->node,
17603 "The 'fixed' value constraint of the attribute use "
17604 "must match the attribute declaration's value "
17605 "constraint '%s'",
17606 decl->defValue);
17607 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017608 }
17609 /*
17610 * FUTURE: One should change the values of the attr. use
17611 * if ever validation should be attempted even if the
17612 * schema itself was not fully valid.
17613 */
17614 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017615 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017616 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17617 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017618}
17619
17620/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017621 * xmlSchemaResolveIDCKeyRef:
17622 * @idc: the identity-constraint definition
17623 * @ctxt: the schema parser context
17624 * @name: the attribute name
17625 *
17626 * Resolve keyRef references to key/unique IDCs.
17627 */
17628static void
17629xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017630 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017631 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017632{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017633 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17634 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017635 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017636 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017637 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017638 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017639 idc->ref->targetNamespace);
17640 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017641 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017642 * TODO: It is actually not an error to fail to resolve.
17643 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017644 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017645 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017646 (xmlSchemaTypePtr) idc, idc->node,
17647 "refer", idc->ref->name,
17648 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017649 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17650 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017651 } else {
17652 if (idc->nbFields !=
17653 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17654 xmlChar *str = NULL;
17655 xmlSchemaIDCPtr refer;
17656
17657 refer = (xmlSchemaIDCPtr) idc->ref->item;
17658 /*
17659 * SPEC c-props-correct(2)
17660 * "If the {identity-constraint category} is keyref,
17661 * the cardinality of the {fields} must equal that of
17662 * the {fields} of the {referenced key}.
17663 */
17664 xmlSchemaPCustomErr(pctxt,
17665 XML_SCHEMAP_C_PROPS_CORRECT,
17666 NULL, (xmlSchemaTypePtr) idc, idc->node,
17667 "The cardinality of the keyref differs from the "
17668 "cardinality of the referenced key '%s'",
17669 xmlSchemaFormatQName(&str, refer->targetNamespace,
17670 refer->name)
17671 );
17672 FREE_AND_NULL(str)
17673 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017674 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017675 }
17676}
17677
17678/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017679 * xmlSchemaParse:
17680 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017681 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017682 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017683 * XML Shema struture which can be used to validate instances.
17684 * *WARNING* this interface is highly subject to change
17685 *
17686 * Returns the internal XML Schema structure built from the resource or
17687 * NULL in case of error
17688 */
17689xmlSchemaPtr
17690xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17691{
17692 xmlSchemaPtr ret = NULL;
17693 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017694 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017695 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017696
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017697 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017698 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017699 * the API; i.e. not automatically by the validated instance document.
17700 */
17701
Daniel Veillard4255d502002-04-16 15:50:10 +000017702 xmlSchemaInitTypes();
17703
Daniel Veillard6045c902002-10-09 21:13:59 +000017704 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017705 return (NULL);
17706
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017707 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017708 ctxt->counter = 0;
17709 ctxt->container = NULL;
17710
17711 /*
17712 * First step is to parse the input document into an DOM/Infoset
17713 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017714 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017715 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017716 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017717 if (doc == NULL) {
17718 xmlSchemaPErr(ctxt, NULL,
17719 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017720 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017721 ctxt->URL, NULL);
17722 return (NULL);
17723 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017724 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017725 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17726 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017727 if (doc == NULL) {
17728 xmlSchemaPErr(ctxt, NULL,
17729 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017730 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017731 NULL, NULL);
17732 return (NULL);
17733 }
17734 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017735 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017736 } else if (ctxt->doc != NULL) {
17737 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017738 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017739 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017740 xmlSchemaPErr(ctxt, NULL,
17741 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017742 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017743 NULL, NULL);
17744 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017745 }
17746
17747 /*
17748 * Then extract the root and Schema parse it
17749 */
17750 root = xmlDocGetRootElement(doc);
17751 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017752 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17753 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017754 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017755 if (!preserve) {
17756 xmlFreeDoc(doc);
17757 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017758 return (NULL);
17759 }
17760
17761 /*
17762 * Remove all the blank text nodes
17763 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017764 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017765
17766 /*
17767 * Then do the parsing for good
17768 */
17769 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017770 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017771 if (!preserve) {
17772 xmlFreeDoc(doc);
17773 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017774 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017775 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017776 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017777 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017778 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017779 ctxt->ctxtType = NULL;
17780 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017781
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017782 /*
17783 * Resolve base types of simple/complex types.
17784 */
17785 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017786
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017787 if (ctxt->nberrors != 0)
17788 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017789
17790 if (ret->volatiles != NULL) {
17791 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17792 int i;
17793 xmlSchemaTreeItemPtr item;
17794
17795 for (i = 0; i < list->nbItems; i++) {
17796 item = (xmlSchemaTreeItemPtr) list->items[i];
17797 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17798 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017799 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017800 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017801 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017802 * Then fixup all attributes declarations
17803 */
17804 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017805 /*
17806 * Then fixup all attributes group declarations
17807 */
17808 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17809 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017810 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017811 * Resolve identity-constraint keyRefs.
17812 */
17813 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017814 /*
17815 * Check type defnitions for circular references.
17816 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017817 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017818 xmlSchemaCheckTypeDefCircular, ctxt);
17819 /*
17820 * Check model groups defnitions for circular references.
17821 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017822 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017823 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017824 /*
17825 * Set the "term" of particles pointing to model group definitions
17826 * to the contained model group.
17827 */
17828 if (ret->volatiles != NULL) {
17829 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17830 int i;
17831 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017832
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017833 for (i = 0; i < list->nbItems; i++) {
17834 item = (xmlSchemaParticlePtr) list->items[i];
17835 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17836 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17837 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017838 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017839 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017840 * Check attribute groups for circular references.
17841 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017842 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17843 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017844 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017845 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017846 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017847 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017848 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017849 /*
17850 * We will stop here if the schema was not valid to avoid internal errors
17851 * on missing sub-components. This is not conforming to the spec, since it
17852 * allows missing components, but it might make further processing crash.
17853 * So see it as a very strict handling, which might be made more lax in the
17854 * future.
17855 */
17856 if (ctxt->nberrors != 0)
17857 goto exit;
17858 /*
17859 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017860 */
17861 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017862 /*
17863 * Validate the value constraint of attribute declarations/uses.
17864 */
17865 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017866 /*
17867 * Validate the value constraint of element declarations.
17868 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017869 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017870
17871 if (ctxt->nberrors != 0)
17872 goto exit;
17873
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017874 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017875 * TODO: cos-element-consistent, cos-all-limited
17876 *
17877 * Then build the content model for all complex types
17878 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017879 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017880 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017881
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017882exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017883 if (ctxt->nberrors != 0) {
17884 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017885 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017886 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017887 return (ret);
17888}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017889
Daniel Veillard4255d502002-04-16 15:50:10 +000017890/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017891 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017892 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017893 * @err: the error callback
17894 * @warn: the warning callback
17895 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017896 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017897 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017898 */
17899void
17900xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017901 xmlSchemaValidityErrorFunc err,
17902 xmlSchemaValidityWarningFunc warn, void *ctx)
17903{
Daniel Veillard4255d502002-04-16 15:50:10 +000017904 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017905 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017906 ctxt->error = err;
17907 ctxt->warning = warn;
17908 ctxt->userData = ctx;
17909}
17910
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017911/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017912 * xmlSchemaGetParserErrors:
17913 * @ctxt: a XMl-Schema parser context
17914 * @err: the error callback result
17915 * @warn: the warning callback result
17916 * @ctx: contextual data for the callbacks result
17917 *
17918 * Get the callback information used to handle errors for a parser context
17919 *
17920 * Returns -1 in case of failure, 0 otherwise
17921 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017922int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017923xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17924 xmlSchemaValidityErrorFunc * err,
17925 xmlSchemaValidityWarningFunc * warn, void **ctx)
17926{
17927 if (ctxt == NULL)
17928 return(-1);
17929 if (err != NULL)
17930 *err = ctxt->error;
17931 if (warn != NULL)
17932 *warn = ctxt->warning;
17933 if (ctx != NULL)
17934 *ctx = ctxt->userData;
17935 return(0);
17936}
17937
17938/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017939 * xmlSchemaFacetTypeToString:
17940 * @type: the facet type
17941 *
17942 * Convert the xmlSchemaTypeType to a char string.
17943 *
17944 * Returns the char string representation of the facet type if the
17945 * type is a facet and an "Internal Error" string otherwise.
17946 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017947static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017948xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17949{
17950 switch (type) {
17951 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017952 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017953 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017954 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017955 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017956 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017957 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017958 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017959 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017960 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017961 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017962 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017963 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017964 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017965 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017966 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017967 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017968 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017969 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017970 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017971 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017972 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017973 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017974 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017975 default:
17976 break;
17977 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017978 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017979}
17980
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017981static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000017982xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
17983{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017984 /*
17985 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000017986 * from xsd:string.
17987 */
17988 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017989 /*
17990 * Note that we assume a whitespace of preserve for anySimpleType.
17991 */
17992 if ((type->builtInType == XML_SCHEMAS_STRING) ||
17993 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
17994 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000017995 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017996 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000017997 else {
17998 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017999 * For all ·atomic· datatypes other than string (and types ·derived·
18000 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000018001 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018002 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018003 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018004 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018005 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018006 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018007 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018008 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018009 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018010 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
18011 } else if (VARIETY_UNION(type)) {
18012 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
18013 } else if (VARIETY_ATOMIC(type)) {
18014 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
18015 return (XML_SCHEMA_WHITESPACE_PRESERVE);
18016 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
18017 return (XML_SCHEMA_WHITESPACE_REPLACE);
18018 else
18019 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018020 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018021 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018022}
18023
Daniel Veillard4255d502002-04-16 15:50:10 +000018024/************************************************************************
18025 * *
18026 * Simple type validation *
18027 * *
18028 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018029
Daniel Veillard4255d502002-04-16 15:50:10 +000018030
18031/************************************************************************
18032 * *
18033 * DOM Validation code *
18034 * *
18035 ************************************************************************/
18036
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018037static void
18038xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18039{
18040 int i, nbItems;
18041 xmlSchemaTypePtr item, *items;
18042
18043
18044 /*
18045 * During the Assemble of the schema ctxt->curItems has
18046 * been filled with the relevant new items. Fix those up.
18047 */
18048 nbItems = ctxt->assemble->nbItems;
18049 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018050
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018051 for (i = 0; i < nbItems; i++) {
18052 item = items[i];
18053 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018054 case XML_SCHEMA_TYPE_COMPLEX:
18055 case XML_SCHEMA_TYPE_SIMPLE:
18056 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18057 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018058 case XML_SCHEMA_TYPE_ATTRIBUTE:
18059 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18060 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018061 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018062 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018063 ctxt, NULL);
18064 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018065 case XML_SCHEMA_TYPE_PARTICLE:
18066 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018067 break;
18068 case XML_SCHEMA_TYPE_IDC_KEY:
18069 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18070 case XML_SCHEMA_TYPE_IDC_KEYREF:
18071 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18072 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018073 default:
18074 break;
18075 }
18076 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018077 if (ctxt->nberrors != 0)
18078 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018079 /*
18080 * Circularity checks.
18081 */
18082 for (i = 0; i < nbItems; i++) {
18083 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018084 switch (item->type) {
18085 case XML_SCHEMA_TYPE_COMPLEX:
18086 case XML_SCHEMA_TYPE_SIMPLE:
18087 xmlSchemaCheckTypeDefCircular(
18088 (xmlSchemaTypePtr) item, ctxt, NULL);
18089 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018090 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018091 xmlSchemaCheckGroupDefCircular(
18092 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018093 break;
18094 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18095 xmlSchemaCheckAttributeGroupCircular(
18096 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18097 break;
18098 default:
18099 break;
18100 }
18101 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018102 if (ctxt->nberrors != 0)
18103 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018104 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018105 * Set the "term" of particles pointing to model group definitions
18106 * to the contained model group.
18107 */
18108 for (i = 0; i < nbItems; i++) {
18109 item = items[i];
18110 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18111 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018112 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018113 XML_SCHEMA_TYPE_GROUP)) {
18114 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18115 ctxt, NULL);
18116 }
18117 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018118 if (ctxt->nberrors != 0)
18119 return;
18120 for (i = 0; i < nbItems; i++) {
18121 item = items[i];
18122 switch (item->type) {
18123 case XML_SCHEMA_TYPE_ELEMENT:
18124 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18125 NULL, NULL, NULL);
18126 break;
18127 default:
18128 break;
18129 }
18130 }
18131 if (ctxt->nberrors != 0)
18132 return;
18133
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018134 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018135 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018136 */
18137 for (i = 0; i < nbItems; i++) {
18138 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018139 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018140 case XML_SCHEMA_TYPE_SIMPLE:
18141 case XML_SCHEMA_TYPE_COMPLEX:
18142 xmlSchemaTypeFixup(item, ctxt, NULL);
18143 break;
18144 default:
18145 break;
18146 }
18147 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018148 if (ctxt->nberrors != 0)
18149 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018150 /*
18151 * Validate value contraint values.
18152 */
18153 for (i = 0; i < nbItems; i++) {
18154 item = items[i];
18155 switch (item->type) {
18156 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018157 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18158 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018159 break;
18160 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018161 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018162 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018163 break;
18164 default:
18165 break;
18166 }
18167 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018168 if (ctxt->nberrors != 0)
18169 return;
18170 /*
18171 * Build the content model for complex types.
18172 */
18173 for (i = 0; i < nbItems; i++) {
18174 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018175 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018176 case XML_SCHEMA_TYPE_COMPLEX:
18177 xmlSchemaBuildContentModel(item, ctxt, NULL);
18178 break;
18179 default:
18180 break;
18181 }
18182 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018183}
18184
18185/**
18186 * xmlSchemaAssembleByLocation:
18187 * @pctxt: a schema parser context
18188 * @vctxt: a schema validation context
18189 * @schema: the existing schema
18190 * @node: the node that fired the assembling
18191 * @nsName: the namespace name of the new schema
18192 * @location: the location of the schema
18193 *
18194 * Expands an existing schema by an additional schema.
18195 *
18196 * Returns 0 if the new schema is correct, a positive error code
18197 * number otherwise and -1 in case of an internal or API error.
18198 */
18199static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018200xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018201 xmlSchemaPtr schema,
18202 xmlNodePtr node,
18203 const xmlChar *nsName,
18204 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018205{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018206 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018207 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018208 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018209 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018210 xmlSchemaParserCtxtPtr pctxt;
18211
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018212 /*
18213 * This should be used:
18214 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018215 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018216 * 3. if requested via the API
18217 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018218 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018219 return (-1);
18220 /*
18221 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018222 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018223 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018224 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18225 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018226 pctxt = vctxt->pctxt;
18227 /*
18228 * Set the counter to produce unique names for anonymous items.
18229 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018230 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018231 /*
18232 * Acquire the schema document.
18233 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018234 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18235 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018236 if (ret != 0) {
18237 if (doc != NULL)
18238 xmlFreeDoc(doc);
18239 } else if (doc != NULL) {
18240 docElem = xmlDocGetRootElement(doc);
18241 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018242 * Create new assemble info.
18243 */
18244 if (pctxt->assemble == NULL) {
18245 pctxt->assemble = xmlSchemaNewAssemble();
18246 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018247 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018248 "Memory error: xmlSchemaAssembleByLocation, "
18249 "allocating assemble info", NULL);
18250 xmlFreeDoc(doc);
18251 return (-1);
18252 }
18253 }
18254 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018255 * Save and reset the context & schema.
18256 */
18257 oldflags = schema->flags;
18258 oldtns = schema->targetNamespace;
18259 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018260 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018261
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018262 xmlSchemaClearSchemaDefaults(schema);
18263 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018264 if ((targetNs != NULL) &&
18265 xmlStrEqual(targetNs, xmlSchemaNs)) {
18266 /*
18267 * We are parsing the schema for schema!
18268 */
18269 vctxt->pctxt->isS4S = 1;
18270 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018271 /* schema->nbCurItems = 0; */
18272 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018273 pctxt->ctxtType = NULL;
18274 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018275
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018276 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18277 if (pctxt->nberrors != 0) {
18278 vctxt->nberrors += pctxt->nberrors;
18279 goto finally;
18280 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018281 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018282 if (pctxt->nberrors != 0) {
18283 vctxt->nberrors += pctxt->nberrors;
18284 goto finally;
18285 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018286 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018287 if (pctxt->nberrors != 0)
18288 vctxt->nberrors += pctxt->nberrors;
18289finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018290 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018291 * Set the counter of items.
18292 */
18293 schema->counter = pctxt->counter;
18294 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018295 * Free the list of assembled components.
18296 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018297 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018298 /*
18299 * Restore the context & schema.
18300 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018301 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018302 schema->flags = oldflags;
18303 schema->targetNamespace = oldtns;
18304 schema->doc = olddoc;
18305 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018306 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018307 return (ret);
18308}
18309
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018310static xmlSchemaAttrInfoPtr
18311xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18312 int metaType)
18313{
18314 if (vctxt->nbAttrInfos == 0)
18315 return (NULL);
18316 {
18317 int i;
18318 xmlSchemaAttrInfoPtr iattr;
18319
18320 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18321 iattr = vctxt->attrInfos[i];
18322 if (iattr->metaType == metaType)
18323 return (iattr);
18324 }
18325
18326 }
18327 return (NULL);
18328}
18329
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018330/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018331 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018332 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018333 *
18334 * Expands an existing schema by an additional schema using
18335 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18336 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18337 * must be set to 1.
18338 *
18339 * Returns 0 if the new schema is correct, a positive error code
18340 * number otherwise and -1 in case of an internal or API error.
18341 */
18342static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018343xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018344{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018345 const xmlChar *cur, *end;
18346 const xmlChar *nsname = NULL, *location;
18347 int count = 0;
18348 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018349 xmlSchemaAttrInfoPtr iattr;
18350
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018351 /*
18352 * Parse the value; we will assume an even number of values
18353 * to be given (this is how Xerces and XSV work).
18354 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018355 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18356 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18357 if (iattr == NULL)
18358 xmlSchemaGetMetaAttrInfo(vctxt,
18359 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18360 if (iattr == NULL)
18361 return (0);
18362 cur = iattr->value;
18363 do {
18364 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018365 /*
18366 * Get the namespace name.
18367 */
18368 while (IS_BLANK_CH(*cur))
18369 cur++;
18370 end = cur;
18371 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18372 end++;
18373 if (end == cur)
18374 break;
18375 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018376 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018377 cur = end;
18378 }
18379 /*
18380 * Get the URI.
18381 */
18382 while (IS_BLANK_CH(*cur))
18383 cur++;
18384 end = cur;
18385 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18386 end++;
18387 if (end == cur)
18388 break;
18389 count++;
18390 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018391 cur = end;
18392 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18393 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018394 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018395 VERROR_INT("xmlSchemaAssembleByXSI",
18396 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018397 return (-1);
18398 }
18399 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018400 return (ret);
18401}
18402
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018403#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018404
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018405static const xmlChar *
18406xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18407 const xmlChar *prefix)
18408{
18409 if (vctxt->sax != NULL) {
18410 int i, j;
18411 xmlSchemaNodeInfoPtr inode;
18412
18413 for (i = vctxt->depth; i >= 0; i--) {
18414 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18415 inode = vctxt->elemInfos[i];
18416 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18417 if (((prefix == NULL) &&
18418 (inode->nsBindings[j] == NULL)) ||
18419 ((prefix != NULL) && xmlStrEqual(prefix,
18420 inode->nsBindings[j]))) {
18421
18422 /*
18423 * Note that the namespace bindings are already
18424 * in a string dict.
18425 */
18426 return (inode->nsBindings[j+1]);
18427 }
18428 }
18429 }
18430 }
18431 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018432#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018433 } else if (vctxt->reader != NULL) {
18434 xmlChar *nsName;
18435
18436 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18437 if (nsName != NULL) {
18438 const xmlChar *ret;
18439
18440 VAL_CREATE_DICT;
18441 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18442 xmlFree(nsName);
18443 return (ret);
18444 } else
18445 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018446#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018447 } else {
18448 xmlNsPtr ns;
18449
18450 if ((vctxt->inode->node == NULL) ||
18451 (vctxt->inode->node->doc == NULL)) {
18452 VERROR_INT("xmlSchemaLookupNamespace",
18453 "no node or node's doc avaliable");
18454 return (NULL);
18455 }
18456 ns = xmlSearchNs(vctxt->inode->node->doc,
18457 vctxt->inode->node, prefix);
18458 if (ns != NULL)
18459 return (ns->href);
18460 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018461 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018462}
18463
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018464/*
18465* This one works on the schema of the validation context.
18466*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018467static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018468xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18469 xmlSchemaPtr schema,
18470 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018471 const xmlChar *value,
18472 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018473 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018474{
18475 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018476
18477 if (vctxt && (vctxt->schema == NULL)) {
18478 VERROR_INT("xmlSchemaValidateNotation",
18479 "a schema is needed on the validation context");
18480 return (-1);
18481 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018482 ret = xmlValidateQName(value, 1);
18483 if (ret != 0)
18484 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018485 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018486 xmlChar *localName = NULL;
18487 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018488
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018489 localName = xmlSplitQName2(value, &prefix);
18490 if (prefix != NULL) {
18491 const xmlChar *nsName = NULL;
18492
18493 if (vctxt != NULL)
18494 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18495 else if (node != NULL) {
18496 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18497 if (ns != NULL)
18498 nsName = ns->href;
18499 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018500 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018501 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018502 return (1);
18503 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018504 if (nsName == NULL) {
18505 xmlFree(prefix);
18506 xmlFree(localName);
18507 return (1);
18508 }
18509 if (xmlHashLookup2(schema->notaDecl, localName,
18510 nsName) != NULL) {
18511 if (valNeeded && (val != NULL)) {
18512 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18513 BAD_CAST xmlStrdup(nsName));
18514 if (*val == NULL)
18515 ret = -1;
18516 }
18517 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018518 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018519 xmlFree(prefix);
18520 xmlFree(localName);
18521 } else {
18522 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18523 if (valNeeded && (val != NULL)) {
18524 (*val) = xmlSchemaNewNOTATIONValue(
18525 BAD_CAST xmlStrdup(value), NULL);
18526 if (*val == NULL)
18527 ret = -1;
18528 }
18529 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018530 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018531 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018532 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018533 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018534}
18535
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018536/************************************************************************
18537 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018538 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018539 * *
18540 ************************************************************************/
18541
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018542/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018543 * xmlSchemaAugmentIDC:
18544 * @idcDef: the IDC definition
18545 *
18546 * Creates an augmented IDC definition item.
18547 *
18548 * Returns the item, or NULL on internal errors.
18549 */
18550static void
18551xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18552 xmlSchemaValidCtxtPtr vctxt)
18553{
18554 xmlSchemaIDCAugPtr aidc;
18555
18556 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18557 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018558 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018559 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18560 NULL);
18561 return;
18562 }
18563 aidc->bubbleDepth = -1;
18564 aidc->def = idcDef;
18565 aidc->next = NULL;
18566 if (vctxt->aidcs == NULL)
18567 vctxt->aidcs = aidc;
18568 else {
18569 aidc->next = vctxt->aidcs;
18570 vctxt->aidcs = aidc;
18571 }
18572}
18573
18574/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018575 * xmlSchemaIDCNewBinding:
18576 * @idcDef: the IDC definition of this binding
18577 *
18578 * Creates a new IDC binding.
18579 *
18580 * Returns the new binding in case of succeeded, NULL on internal errors.
18581 */
18582static xmlSchemaPSVIIDCBindingPtr
18583xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18584{
18585 xmlSchemaPSVIIDCBindingPtr ret;
18586
18587 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18588 sizeof(xmlSchemaPSVIIDCBinding));
18589 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018590 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018591 "allocating a PSVI IDC binding item", NULL);
18592 return (NULL);
18593 }
18594 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18595 ret->definition = idcDef;
18596 return (ret);
18597}
18598
18599/**
18600 * xmlSchemaIDCStoreNodeTableItem:
18601 * @vctxt: the WXS validation context
18602 * @item: the IDC node table item
18603 *
18604 * The validation context is used to store an IDC node table items.
18605 * They are stored to avoid copying them if IDC node-tables are merged
18606 * with corresponding parent IDC node-tables (bubbling).
18607 *
18608 * Returns 0 if succeeded, -1 on internal errors.
18609 */
18610static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018611xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018612 xmlSchemaPSVIIDCNodePtr item)
18613{
18614 /*
18615 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018616 */
18617 if (vctxt->idcNodes == NULL) {
18618 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018619 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18620 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018621 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018622 "allocating the IDC node table item list", NULL);
18623 return (-1);
18624 }
18625 vctxt->sizeIdcNodes = 20;
18626 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18627 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018628 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18629 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018630 sizeof(xmlSchemaPSVIIDCNodePtr));
18631 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018632 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018633 "re-allocating the IDC node table item list", NULL);
18634 return (-1);
18635 }
18636 }
18637 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018638
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018639 return (0);
18640}
18641
18642/**
18643 * xmlSchemaIDCStoreKey:
18644 * @vctxt: the WXS validation context
18645 * @item: the IDC key
18646 *
18647 * The validation context is used to store an IDC key.
18648 *
18649 * Returns 0 if succeeded, -1 on internal errors.
18650 */
18651static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018652xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018653 xmlSchemaPSVIIDCKeyPtr key)
18654{
18655 /*
18656 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018657 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018658 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018659 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018660 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18661 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018662 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018663 "allocating the IDC key storage list", NULL);
18664 return (-1);
18665 }
18666 vctxt->sizeIdcKeys = 40;
18667 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18668 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018669 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18670 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018671 sizeof(xmlSchemaPSVIIDCKeyPtr));
18672 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018673 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018674 "re-allocating the IDC key storage list", NULL);
18675 return (-1);
18676 }
18677 }
18678 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018679
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018680 return (0);
18681}
18682
18683/**
18684 * xmlSchemaIDCAppendNodeTableItem:
18685 * @bind: the IDC binding
18686 * @ntItem: the node-table item
18687 *
18688 * Appends the IDC node-table item to the binding.
18689 *
18690 * Returns 0 on success and -1 on internal errors.
18691 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018692static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018693xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18694 xmlSchemaPSVIIDCNodePtr ntItem)
18695{
18696 if (bind->nodeTable == NULL) {
18697 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018698 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018699 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18700 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018701 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018702 "allocating an array of IDC node-table items", NULL);
18703 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018704 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018705 } else if (bind->sizeNodes <= bind->nbNodes) {
18706 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018707 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18708 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018709 sizeof(xmlSchemaPSVIIDCNodePtr));
18710 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018711 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018712 "re-allocating an array of IDC node-table items", NULL);
18713 return(-1);
18714 }
18715 }
18716 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018717 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018718}
18719
18720/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018721 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018722 * @vctxt: the WXS validation context
18723 * @matcher: the IDC matcher
18724 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018725 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018726 * of the given matcher. If none found, a new one is created
18727 * and added to the IDC table.
18728 *
18729 * Returns an IDC binding or NULL on internal errors.
18730 */
18731static xmlSchemaPSVIIDCBindingPtr
18732xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18733 xmlSchemaIDCMatcherPtr matcher)
18734{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018735 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018736
18737 info = vctxt->elemInfos[matcher->depth];
18738
18739 if (info->idcTable == NULL) {
18740 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18741 if (info->idcTable == NULL)
18742 return (NULL);
18743 return(info->idcTable);
18744 } else {
18745 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018746
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018747 bind = info->idcTable;
18748 do {
18749 if (bind->definition == matcher->aidc->def)
18750 return(bind);
18751 if (bind->next == NULL) {
18752 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18753 if (bind->next == NULL)
18754 return (NULL);
18755 return(bind->next);
18756 }
18757 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018758 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018759 }
18760 return (NULL);
18761}
18762
18763/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018764 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018765 * @key: the IDC key
18766 *
18767 * Frees an IDC key together with its compiled value.
18768 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018769static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018770xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18771{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018772 if (key->val != NULL)
18773 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018774 xmlFree(key);
18775}
18776
18777/**
18778 * xmlSchemaIDCFreeBinding:
18779 *
18780 * Frees an IDC binding. Note that the node table-items
18781 * are not freed.
18782 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018783static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018784xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18785{
18786 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018787 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18788 int i;
18789 /*
18790 * Node-table items for keyrefs are not stored globally
18791 * to the validation context, since they are not bubbled.
18792 * We need to free them here.
18793 */
18794 for (i = 0; i < bind->nbNodes; i++) {
18795 xmlFree(bind->nodeTable[i]->keys);
18796 xmlFree(bind->nodeTable[i]);
18797 }
18798 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018799 xmlFree(bind->nodeTable);
18800 }
18801 xmlFree(bind);
18802}
18803
18804/**
18805 * xmlSchemaIDCFreeIDCTable:
18806 * @bind: the first IDC binding in the list
18807 *
18808 * Frees an IDC table, i.e. all the IDC bindings in the list.
18809 */
18810static void
18811xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18812{
18813 xmlSchemaPSVIIDCBindingPtr prev;
18814
18815 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018816 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018817 bind = bind->next;
18818 xmlSchemaIDCFreeBinding(prev);
18819 }
18820}
18821
18822/**
18823 * xmlSchemaIDCFreeMatcherList:
18824 * @matcher: the first IDC matcher in the list
18825 *
18826 * Frees a list of IDC matchers.
18827 */
18828static void
18829xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18830{
18831 xmlSchemaIDCMatcherPtr next;
18832
18833 while (matcher != NULL) {
18834 next = matcher->next;
18835 if (matcher->keySeqs != NULL) {
18836 int i;
18837 for (i = 0; i < matcher->sizeKeySeqs; i++)
18838 if (matcher->keySeqs[i] != NULL)
18839 xmlFree(matcher->keySeqs[i]);
18840 xmlFree(matcher->keySeqs);
18841 }
18842 xmlFree(matcher);
18843 matcher = next;
18844 }
18845}
18846
18847/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018848 * xmlSchemaIDCAddStateObject:
18849 * @vctxt: the WXS validation context
18850 * @matcher: the IDC matcher
18851 * @sel: the XPath information
18852 * @parent: the parent "selector" state object if any
18853 * @type: "selector" or "field"
18854 *
18855 * Creates/reuses and activates state objects for the given
18856 * XPath information; if the XPath expression consists of unions,
18857 * multiple state objects are created for every unioned expression.
18858 *
18859 * Returns 0 on success and -1 on internal errors.
18860 */
18861static int
18862xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18863 xmlSchemaIDCMatcherPtr matcher,
18864 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018865 int type)
18866{
18867 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018868
18869 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018870 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018871 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018872 if (vctxt->xpathStatePool != NULL) {
18873 sto = vctxt->xpathStatePool;
18874 vctxt->xpathStatePool = sto->next;
18875 sto->next = NULL;
18876 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018877 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018878 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018879 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018880 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18881 if (sto == NULL) {
18882 xmlSchemaVErrMemory(NULL,
18883 "allocating an IDC state object", NULL);
18884 return (-1);
18885 }
18886 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18887 }
18888 /*
18889 * Add to global list.
18890 */
18891 if (vctxt->xpathStates != NULL)
18892 sto->next = vctxt->xpathStates;
18893 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018894
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018895 /*
18896 * Free the old xpath validation context.
18897 */
18898 if (sto->xpathCtxt != NULL)
18899 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18900
18901 /*
18902 * Create a new XPath (pattern) validation context.
18903 */
18904 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18905 (xmlPatternPtr) sel->xpathComp);
18906 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018907 VERROR_INT("xmlSchemaIDCAddStateObject",
18908 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018909 return (-1);
18910 }
18911 sto->type = type;
18912 sto->depth = vctxt->depth;
18913 sto->matcher = matcher;
18914 sto->sel = sel;
18915 sto->nbHistory = 0;
18916
18917#if DEBUG_IDC
18918 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18919 sto->sel->xpath);
18920#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018921 return (0);
18922}
18923
18924/**
18925 * xmlSchemaXPathEvaluate:
18926 * @vctxt: the WXS validation context
18927 * @nodeType: the nodeType of the current node
18928 *
18929 * Evaluates all active XPath state objects.
18930 *
18931 * Returns the number of IC "field" state objects which resolved to
18932 * this node, 0 if none resolved and -1 on internal errors.
18933 */
18934static int
18935xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018936 xmlElementType nodeType)
18937{
18938 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018939 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018940
18941 if (vctxt->xpathStates == NULL)
18942 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018943
18944 if (nodeType == XML_ATTRIBUTE_NODE)
18945 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018946#if DEBUG_IDC
18947 {
18948 xmlChar *str = NULL;
18949 xmlGenericError(xmlGenericErrorContext,
18950 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018951 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18952 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018953 FREE_AND_NULL(str)
18954 }
18955#endif
18956 /*
18957 * Process all active XPath state objects.
18958 */
18959 first = vctxt->xpathStates;
18960 sto = first;
18961 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018962#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018963 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018964 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
18965 sto->matcher->aidc->def->name, sto->sel->xpath);
18966 else
18967 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
18968 sto->matcher->aidc->def->name, sto->sel->xpath);
18969#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018970 if (nodeType == XML_ELEMENT_NODE)
18971 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018972 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018973 else
18974 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018975 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018976
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018977 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018978 VERROR_INT("xmlSchemaXPathEvaluate",
18979 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018980 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018981 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018982 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018983 goto next_sto;
18984 /*
18985 * Full match.
18986 */
18987#if DEBUG_IDC
18988 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018989 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018990#endif
18991 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018992 * Register a match in the state object history.
18993 */
18994 if (sto->history == NULL) {
18995 sto->history = (int *) xmlMalloc(5 * sizeof(int));
18996 if (sto->history == NULL) {
18997 xmlSchemaVErrMemory(NULL,
18998 "allocating the state object history", NULL);
18999 return(-1);
19000 }
19001 sto->sizeHistory = 10;
19002 } else if (sto->sizeHistory <= sto->nbHistory) {
19003 sto->sizeHistory *= 2;
19004 sto->history = (int *) xmlRealloc(sto->history,
19005 sto->sizeHistory * sizeof(int));
19006 if (sto->history == NULL) {
19007 xmlSchemaVErrMemory(NULL,
19008 "re-allocating the state object history", NULL);
19009 return(-1);
19010 }
19011 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019012 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019013
19014#ifdef DEBUG_IDC
19015 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19016 vctxt->depth);
19017#endif
19018
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019019 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19020 xmlSchemaIDCSelectPtr sel;
19021 /*
19022 * Activate state objects for the IDC fields of
19023 * the IDC selector.
19024 */
19025#if DEBUG_IDC
19026 xmlGenericError(xmlGenericErrorContext, "IDC: "
19027 "activating field states\n");
19028#endif
19029 sel = sto->matcher->aidc->def->fields;
19030 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019031 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19032 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19033 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019034 sel = sel->next;
19035 }
19036 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19037 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019038 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019039 */
19040#if DEBUG_IDC
19041 xmlGenericError(xmlGenericErrorContext,
19042 "IDC: key found\n");
19043#endif
19044 /*
19045 * Notify that the character value of this node is
19046 * needed.
19047 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019048 if (resolved == 0) {
19049 if ((vctxt->inode->flags &
19050 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19051 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19052 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019053 resolved++;
19054 }
19055next_sto:
19056 if (sto->next == NULL) {
19057 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019058 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019059 */
19060 head = first;
19061 sto = vctxt->xpathStates;
19062 } else
19063 sto = sto->next;
19064 }
19065 return (resolved);
19066}
19067
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019068static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019069xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019070 xmlChar **buf,
19071 xmlSchemaPSVIIDCKeyPtr *seq,
19072 int count)
19073{
19074 int i, res;
19075 const xmlChar *value = NULL;
19076
19077 *buf = xmlStrdup(BAD_CAST "[");
19078 for (i = 0; i < count; i++) {
19079 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019080 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19081 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019082 if (res == 0)
19083 *buf = xmlStrcat(*buf, value);
19084 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019085 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19086 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019087 *buf = xmlStrcat(*buf, BAD_CAST "???");
19088 }
19089 if (i < count -1)
19090 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19091 else
19092 *buf = xmlStrcat(*buf, BAD_CAST "'");
19093 if (value != NULL) {
19094 xmlFree((xmlChar *) value);
19095 value = NULL;
19096 }
19097 }
19098 *buf = xmlStrcat(*buf, BAD_CAST "]");
19099
19100 return (BAD_CAST *buf);
19101}
19102
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019103/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019104 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019105 * @vctxt: the WXS validation context
19106 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019107 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019108 *
19109 * Processes and pops the history items of the IDC state objects.
19110 * IDC key-sequences are validated/created on IDC bindings.
19111 *
19112 * Returns 0 on success and -1 on internal errors.
19113 */
19114static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019115xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019116 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019117{
19118 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019119 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019120 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019121 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019122
19123 if (vctxt->xpathStates == NULL)
19124 return (0);
19125 sto = vctxt->xpathStates;
19126
19127#if DEBUG_IDC
19128 {
19129 xmlChar *str = NULL;
19130 xmlGenericError(xmlGenericErrorContext,
19131 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019132 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19133 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019134 FREE_AND_NULL(str)
19135 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019136#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019137 /*
19138 * Evaluate the state objects.
19139 */
19140 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019141 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19142 if (res == -1) {
19143 VERROR_INT("xmlSchemaXPathProcessHistory",
19144 "calling xmlStreamPop()");
19145 return (-1);
19146 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019147#if DEBUG_IDC
19148 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19149 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019150#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019151 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019152 goto deregister_check;
19153
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019154 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019155
19156 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019157 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019158 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019159 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019160 sto = sto->next;
19161 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019162 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019163 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19164 if (! IS_SIMPLE_TYPE(type)) {
19165 /*
19166 * Not qualified if the field resolves to a node of non
19167 * simple type.
19168 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019169 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19170 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019171 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19172 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019173 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019174
19175 sto->nbHistory--;
19176 goto deregister_check;
19177 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019178 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019179 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019180 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019181 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019182 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019183 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019184 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19185 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019186 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019187 sto->nbHistory--;
19188 goto deregister_check;
19189 } else {
19190 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19191 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019192 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019193
19194 /*
19195 * The key will be anchored on the matcher's list of
19196 * key-sequences. The position in this list is determined
19197 * by the target node's depth relative to the matcher's
19198 * depth of creation (i.e. the depth of the scope element).
19199 */
19200 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019201 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019202
19203 /*
19204 * Create/grow the array of key-sequences.
19205 */
19206 if (matcher->keySeqs == NULL) {
19207 if (pos > 9)
19208 matcher->sizeKeySeqs = pos * 2;
19209 else
19210 matcher->sizeKeySeqs = 10;
19211 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19212 xmlMalloc(matcher->sizeKeySeqs *
19213 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19214 if (matcher->keySeqs == NULL) {
19215 xmlSchemaVErrMemory(NULL,
19216 "allocating an array of key-sequences",
19217 NULL);
19218 return(-1);
19219 }
19220 memset(matcher->keySeqs, 0,
19221 matcher->sizeKeySeqs *
19222 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19223 } else if (pos >= matcher->sizeKeySeqs) {
19224 int i = matcher->sizeKeySeqs;
19225
19226 matcher->sizeKeySeqs *= 2;
19227 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19228 xmlRealloc(matcher->keySeqs,
19229 matcher->sizeKeySeqs *
19230 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019231 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019232 xmlSchemaVErrMemory(NULL,
19233 "reallocating an array of key-sequences",
19234 NULL);
19235 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019236 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019237 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019238 * The array needs to be NULLed.
19239 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019240 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019241 for (; i < matcher->sizeKeySeqs; i++)
19242 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019243 }
19244
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019245 /*
19246 * Get/create the key-sequence.
19247 */
19248 keySeq = matcher->keySeqs[pos];
19249 if (keySeq == NULL) {
19250 goto create_sequence;
19251 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019252 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019253 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019254 * cvc-identity-constraint:
19255 * 3 For each node in the ·target node set· all
19256 * of the {fields}, with that node as the context
19257 * node, evaluate to either an empty node-set or
19258 * a node-set with exactly one member, which must
19259 * have a simple type.
19260 *
19261 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019262 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019263 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19264 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019265 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019266 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019267 "with more than one member",
19268 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019269 sto->nbHistory--;
19270 goto deregister_check;
19271 } else {
19272 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019273 }
19274 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019275
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019276create_sequence:
19277 /*
19278 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019279 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019280 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19281 matcher->aidc->def->nbFields *
19282 sizeof(xmlSchemaPSVIIDCKeyPtr));
19283 if (keySeq == NULL) {
19284 xmlSchemaVErrMemory(NULL,
19285 "allocating an IDC key-sequence", NULL);
19286 return(-1);
19287 }
19288 memset(keySeq, 0, matcher->aidc->def->nbFields *
19289 sizeof(xmlSchemaPSVIIDCKeyPtr));
19290 matcher->keySeqs[pos] = keySeq;
19291create_key:
19292 /*
19293 * Created a key once per node only.
19294 */
19295 if (key == NULL) {
19296 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19297 sizeof(xmlSchemaPSVIIDCKey));
19298 if (key == NULL) {
19299 xmlSchemaVErrMemory(NULL,
19300 "allocating a IDC key", NULL);
19301 xmlFree(keySeq);
19302 matcher->keySeqs[pos] = NULL;
19303 return(-1);
19304 }
19305 /*
19306 * Consume the compiled value.
19307 */
19308 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019309 key->val = vctxt->inode->val;
19310 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019311 /*
19312 * Store the key in a global list.
19313 */
19314 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19315 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019316 return (-1);
19317 }
19318 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019319 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019320 }
19321 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019322
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019323 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19324 xmlSchemaPSVIIDCBindingPtr bind;
19325 xmlSchemaPSVIIDCNodePtr ntItem;
19326 xmlSchemaIDCMatcherPtr matcher;
19327 xmlSchemaIDCPtr idc;
19328 int pos, i, j, nbKeys;
19329 /*
19330 * Here we have the following scenario:
19331 * An IDC 'selector' state object resolved to a target node,
19332 * during the time this target node was in the
19333 * ancestor-or-self axis, the 'field' state object(s) looked
19334 * out for matching nodes to create a key-sequence for this
19335 * target node. Now we are back to this target node and need
19336 * to put the key-sequence, together with the target node
19337 * itself, into the node-table of the corresponding IDC
19338 * binding.
19339 */
19340 matcher = sto->matcher;
19341 idc = matcher->aidc->def;
19342 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019343 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019344 /*
19345 * Check if the matcher has any key-sequences at all, plus
19346 * if it has a key-sequence for the current target node.
19347 */
19348 if ((matcher->keySeqs == NULL) ||
19349 (matcher->sizeKeySeqs <= pos)) {
19350 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19351 goto selector_key_error;
19352 else
19353 goto selector_leave;
19354 }
19355
19356 keySeq = &(matcher->keySeqs[pos]);
19357 if (*keySeq == NULL) {
19358 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19359 goto selector_key_error;
19360 else
19361 goto selector_leave;
19362 }
19363
19364 for (i = 0; i < nbKeys; i++) {
19365 if ((*keySeq)[i] == NULL) {
19366 /*
19367 * Not qualified, if not all fields did resolve.
19368 */
19369 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19370 /*
19371 * All fields of a "key" IDC must resolve.
19372 */
19373 goto selector_key_error;
19374 }
19375 goto selector_leave;
19376 }
19377 }
19378 /*
19379 * All fields did resolve.
19380 */
19381
19382 /*
19383 * 4.1 If the {identity-constraint category} is unique(/key),
19384 * then no two members of the ·qualified node set· have
19385 * ·key-sequences· whose members are pairwise equal, as
19386 * defined by Equal in [XML Schemas: Datatypes].
19387 *
19388 * Get the IDC binding from the matcher and check for
19389 * duplicate key-sequences.
19390 */
19391 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19392 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19393 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019394 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019395
19396 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019397 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019398 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019399 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019400 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019401 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019402 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019403 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019404 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019405 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019406 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019407 if (res == -1) {
19408 return (-1);
19409 } else if (res == 0)
19410 break;
19411 }
19412 if (res == 1) {
19413 /*
19414 * Duplicate found.
19415 */
19416 break;
19417 }
19418 i++;
19419 } while (i < bind->nbNodes);
19420 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019421 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019422 /*
19423 * TODO: Try to report the key-sequence.
19424 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019425 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19426 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019427 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019428 "Duplicate key-sequence %s",
19429 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19430 (*keySeq), nbKeys), NULL);
19431 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019432 goto selector_leave;
19433 }
19434 }
19435 /*
19436 * Add a node-table item to the IDC binding.
19437 */
19438 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19439 sizeof(xmlSchemaPSVIIDCNode));
19440 if (ntItem == NULL) {
19441 xmlSchemaVErrMemory(NULL,
19442 "allocating an IDC node-table item", NULL);
19443 xmlFree(*keySeq);
19444 *keySeq = NULL;
19445 return(-1);
19446 }
19447 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19448
19449 /*
19450 * Store the node-table item on global list.
19451 */
19452 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19453 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19454 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019455 xmlFree(*keySeq);
19456 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019457 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019458 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019459 }
19460 /*
19461 * Init the node-table item. Consume the key-sequence.
19462 */
19463 ntItem->node = vctxt->node;
19464 ntItem->keys = *keySeq;
19465 *keySeq = NULL;
19466 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19467 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19468 /*
19469 * Free the item, since keyref items won't be
19470 * put on a global list.
19471 */
19472 xmlFree(ntItem->keys);
19473 xmlFree(ntItem);
19474 }
19475 return (-1);
19476 }
19477
19478 goto selector_leave;
19479selector_key_error:
19480 /*
19481 * 4.2.1 (KEY) The ·target node set· and the
19482 * ·qualified node set· are equal, that is, every
19483 * member of the ·target node set· is also a member
19484 * of the ·qualified node set· and vice versa.
19485 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019486 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19487 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019488selector_leave:
19489 /*
19490 * Free the key-sequence if not added to the IDC table.
19491 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019492 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019493 xmlFree(*keySeq);
19494 *keySeq = NULL;
19495 }
19496 } /* if selector */
19497
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019498 sto->nbHistory--;
19499
19500deregister_check:
19501 /*
19502 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019503 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019504 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019505#if DEBUG_IDC
19506 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19507 sto->sel->xpath);
19508#endif
19509 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019510 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019511 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019512 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019513 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019514 nextsto = sto->next;
19515 /*
19516 * Unlink from the list of active XPath state objects.
19517 */
19518 vctxt->xpathStates = sto->next;
19519 sto->next = vctxt->xpathStatePool;
19520 /*
19521 * Link it to the pool of reusable state objects.
19522 */
19523 vctxt->xpathStatePool = sto;
19524 sto = nextsto;
19525 } else
19526 sto = sto->next;
19527 } /* while (sto != NULL) */
19528 return (0);
19529}
19530
19531/**
19532 * xmlSchemaIDCRegisterMatchers:
19533 * @vctxt: the WXS validation context
19534 * @elemDecl: the element declaration
19535 *
19536 * Creates helper objects to evaluate IDC selectors/fields
19537 * successively.
19538 *
19539 * Returns 0 if OK and -1 on internal errors.
19540 */
19541static int
19542xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19543 xmlSchemaElementPtr elemDecl)
19544{
19545 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19546 xmlSchemaIDCPtr idc, refIdc;
19547 xmlSchemaIDCAugPtr aidc;
19548
19549 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19550 if (idc == NULL)
19551 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019552
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019553#if DEBUG_IDC
19554 {
19555 xmlChar *str = NULL;
19556 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019557 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019558 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19559 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019560 FREE_AND_NULL(str)
19561 }
19562#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019563 if (vctxt->inode->idcMatchers != NULL) {
19564 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19565 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019566 return (-1);
19567 }
19568 do {
19569 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19570 /*
19571 * Since IDCs bubbles are expensive we need to know the
19572 * depth at which the bubbles should stop; this will be
19573 * the depth of the top-most keyref IDC. If no keyref
19574 * references a key/unique IDC, the bubbleDepth will
19575 * be -1, indicating that no bubbles are needed.
19576 */
19577 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19578 if (refIdc != NULL) {
19579 /*
19580 * Lookup the augmented IDC.
19581 */
19582 aidc = vctxt->aidcs;
19583 while (aidc != NULL) {
19584 if (aidc->def == refIdc)
19585 break;
19586 aidc = aidc->next;
19587 }
19588 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019589 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019590 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019591 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019592 return (-1);
19593 }
19594 if ((aidc->bubbleDepth == -1) ||
19595 (vctxt->depth < aidc->bubbleDepth))
19596 aidc->bubbleDepth = vctxt->depth;
19597 }
19598 }
19599 /*
19600 * Lookup the augmented IDC item for the IDC definition.
19601 */
19602 aidc = vctxt->aidcs;
19603 while (aidc != NULL) {
19604 if (aidc->def == idc)
19605 break;
19606 aidc = aidc->next;
19607 }
19608 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019609 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19610 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019611 return (-1);
19612 }
19613 /*
19614 * Create an IDC matcher for every IDC definition.
19615 */
19616 matcher = (xmlSchemaIDCMatcherPtr)
19617 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19618 if (matcher == NULL) {
19619 xmlSchemaVErrMemory(vctxt,
19620 "allocating an IDC matcher", NULL);
19621 return (-1);
19622 }
19623 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19624 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019625 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019626 else
19627 last->next = matcher;
19628 last = matcher;
19629
19630 matcher->type = IDC_MATCHER;
19631 matcher->depth = vctxt->depth;
19632 matcher->aidc = aidc;
19633#if DEBUG_IDC
19634 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19635#endif
19636 /*
19637 * Init the automaton state object.
19638 */
19639 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019640 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019641 return (-1);
19642
19643 idc = idc->next;
19644 } while (idc != NULL);
19645 return (0);
19646}
19647
19648/**
19649 * xmlSchemaBubbleIDCNodeTables:
19650 * @depth: the current tree depth
19651 *
19652 * Merges IDC bindings of an element at @depth into the corresponding IDC
19653 * bindings of its parent element. If a duplicate note-table entry is found,
19654 * both, the parent node-table entry and child entry are discarded from the
19655 * node-table of the parent.
19656 *
19657 * Returns 0 if OK and -1 on internal errors.
19658 */
19659static int
19660xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19661{
19662 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019663 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19664 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019665 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19666 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019667 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019668 int duplTop;
19669
19670 /*
19671 * The node table has the following sections:
19672 *
19673 * O --> old node-table entries (first)
19674 * O
19675 * + --> new node-table entries
19676 * +
19677 * % --> new duplicate node-table entries
19678 * %
19679 * # --> old duplicate node-table entries
19680 * # (last)
19681 *
19682 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019683 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019684 if (bind == NULL) {
19685 /* Fine, no table, no bubbles. */
19686 return (0);
19687 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019688
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019689 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19690 /*
19691 * Walk all bindings; create new or add to existing bindings.
19692 * Remove duplicate key-sequences.
19693 */
19694start_binding:
19695 while (bind != NULL) {
19696 /*
19697 * Skip keyref IDCs.
19698 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019699 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19700 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019701 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019702 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019703 /*
19704 * Check if the key/unique IDC table needs to be bubbled.
19705 */
19706 aidc = vctxt->aidcs;
19707 do {
19708 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019709 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019710 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019711 bind = bind->next;
19712 goto start_binding;
19713 }
19714 break;
19715 }
19716 aidc = aidc->next;
19717 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019718
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019719 if (parTable != NULL)
19720 parBind = *parTable;
19721 while (parBind != NULL) {
19722 /*
19723 * Search a matching parent binding for the
19724 * IDC definition.
19725 */
19726 if (parBind->definition == bind->definition) {
19727
19728 /*
19729 * Compare every node-table entry of the child node,
19730 * i.e. the key-sequence within, ...
19731 */
19732 oldNum = parBind->nbNodes; /* Skip newly added items. */
19733 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019734 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019735
19736 for (i = 0; i < bind->nbNodes; i++) {
19737 node = bind->nodeTable[i];
19738 if (node == NULL)
19739 continue;
19740 /*
19741 * ...with every key-sequence of the parent node, already
19742 * evaluated to be a duplicate key-sequence.
19743 */
19744 if (parBind->nbDupls != 0) {
19745 j = bind->nbNodes + newDupls;
19746 while (j < duplTop) {
19747 parNode = parBind->nodeTable[j];
19748 for (k = 0; k < bind->definition->nbFields; k++) {
19749 key = node->keys[k];
19750 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019751 ret = xmlSchemaAreValuesEqual(key->val,
19752 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019753 if (ret == -1) {
19754 /* TODO: Internal error */
19755 return(-1);
19756 } else if (ret == 0)
19757 break;
19758
19759 }
19760 if (ret == 1)
19761 /* Duplicate found. */
19762 break;
19763 j++;
19764 }
19765 if (j != duplTop) {
19766 /* Duplicate found. */
19767 continue;
19768 }
19769 }
19770 /*
19771 * ... and with every key-sequence of the parent node.
19772 */
19773 j = 0;
19774 while (j < oldNum) {
19775 parNode = parBind->nodeTable[j];
19776 /*
19777 * Compare key by key.
19778 */
19779 for (k = 0; k < parBind->definition->nbFields; k++) {
19780 key = node->keys[k];
19781 parKey = parNode->keys[k];
19782
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019783 ret = xmlSchemaAreValuesEqual(key->val,
19784 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019785 if (ret == -1) {
19786 /* TODO: Internal error */
19787 } else if (ret == 0)
19788 break;
19789
19790 }
19791 if (ret == 1)
19792 /*
19793 * The key-sequences are equal.
19794 */
19795 break;
19796 j++;
19797 }
19798 if (j != oldNum) {
19799 /*
19800 * Handle duplicates.
19801 */
19802 newDupls++;
19803 oldNum--;
19804 parBind->nbNodes--;
19805 /*
19806 * Move last old item to pos of duplicate.
19807 */
19808 parBind->nodeTable[j] =
19809 parBind->nodeTable[oldNum];
19810
19811 if (parBind->nbNodes != oldNum) {
19812 /*
19813 * If new items exist, move last new item to
19814 * last of old items.
19815 */
19816 parBind->nodeTable[oldNum] =
19817 parBind->nodeTable[parBind->nbNodes];
19818 }
19819 /*
19820 * Move duplicate to last pos of new/old items.
19821 */
19822 parBind->nodeTable[parBind->nbNodes] = parNode;
19823
19824 } else {
19825 /*
19826 * Add the node-table entry (node and key-sequence) of
19827 * the child node to the node table of the parent node.
19828 */
19829 if (parBind->nodeTable == NULL) {
19830 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019831 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019832 if (parBind->nodeTable == NULL) {
19833 xmlSchemaVErrMemory(NULL,
19834 "allocating IDC list of node-table items", NULL);
19835 return(-1);
19836 }
19837 parBind->sizeNodes = 1;
19838 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019839 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019840 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19841 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19842 sizeof(xmlSchemaPSVIIDCNodePtr));
19843 if (parBind->nodeTable == NULL) {
19844 xmlSchemaVErrMemory(NULL,
19845 "re-allocating IDC list of node-table items", NULL);
19846 return(-1);
19847 }
19848 }
19849
19850 /*
19851 * Move first old duplicate to last position
19852 * of old duplicates +1.
19853 */
19854 if (parBind->nbDupls != 0) {
19855 parBind->nodeTable[duplTop] =
19856 parBind->nodeTable[parBind->nbNodes + newDupls];
19857 }
19858 /*
19859 * Move first new duplicate to last position of
19860 * new duplicates +1.
19861 */
19862 if (newDupls != 0) {
19863 parBind->nodeTable[parBind->nbNodes + newDupls] =
19864 parBind->nodeTable[parBind->nbNodes];
19865 }
19866 /*
19867 * Append the new node-table entry to the 'new node-table
19868 * entries' section.
19869 */
19870 parBind->nodeTable[parBind->nbNodes] = node;
19871 parBind->nbNodes++;
19872 duplTop++;
19873 }
19874 }
19875 parBind->nbDupls += newDupls;
19876 break;
19877 }
19878 if (parBind->next == NULL)
19879 lastParBind = parBind;
19880 parBind = parBind->next;
19881 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019882 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019883 /*
19884 * No binding for the IDC was found: create a new one and
19885 * copy all node-tables.
19886 */
19887 parBind = xmlSchemaIDCNewBinding(bind->definition);
19888 if (parBind == NULL)
19889 return(-1);
19890
19891 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19892 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19893 if (parBind->nodeTable == NULL) {
19894 xmlSchemaVErrMemory(NULL,
19895 "allocating an array of IDC node-table items", NULL);
19896 xmlSchemaIDCFreeBinding(parBind);
19897 return(-1);
19898 }
19899 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019900 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019901 memcpy(parBind->nodeTable, bind->nodeTable,
19902 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019903 if (*parTable == NULL)
19904 *parTable = parBind;
19905 else
19906 lastParBind->next = parBind;
19907 }
19908 bind = bind->next;
19909 }
19910 return (0);
19911}
19912
19913/**
19914 * xmlSchemaCheckCVCIDCKeyRef:
19915 * @vctxt: the WXS validation context
19916 * @elemDecl: the element declaration
19917 *
19918 * Check the cvc-idc-keyref constraints.
19919 */
19920static int
19921xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19922{
19923 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19924
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019925 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019926 /*
19927 * Find a keyref.
19928 */
19929 while (refbind != NULL) {
19930 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19931 int i, j, k, res;
19932 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19933 xmlSchemaPSVIIDCKeyPtr refKey, key;
19934
19935 /*
19936 * Find the referred key/unique.
19937 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019938 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019939 do {
19940 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19941 bind->definition)
19942 break;
19943 bind = bind->next;
19944 } while (bind != NULL);
19945
19946 /*
19947 * Search for a matching key-sequences.
19948 */
19949 for (i = 0; i < refbind->nbNodes; i++) {
19950 res = 0;
19951 if (bind != NULL) {
19952 refKeys = refbind->nodeTable[i]->keys;
19953 for (j = 0; j < bind->nbNodes; j++) {
19954 keys = bind->nodeTable[j]->keys;
19955 for (k = 0; k < bind->definition->nbFields; k++) {
19956 refKey = refKeys[k];
19957 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019958 res = xmlSchemaAreValuesEqual(key->val,
19959 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019960 if (res == 0)
19961 break;
19962 else if (res == -1) {
19963 return (-1);
19964 }
19965 }
19966 if (res == 1) {
19967 /*
19968 * Match found.
19969 */
19970 break;
19971 }
19972 }
19973 }
19974 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019975 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019976 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019977 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19978 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019979 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019980 "No match found for key-sequence %s of key "
19981 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019982 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019983 refbind->nodeTable[i]->keys,
19984 refbind->definition->nbFields),
19985 xmlSchemaFormatQName(&strB,
19986 refbind->definition->targetNamespace,
19987 refbind->definition->name));
19988 FREE_AND_NULL(str);
19989 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019990 }
19991 }
19992 }
19993 refbind = refbind->next;
19994 }
19995 return (0);
19996}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019997
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019998/************************************************************************
19999 * *
20000 * XML Reader validation code *
20001 * *
20002 ************************************************************************/
20003
20004static xmlSchemaAttrInfoPtr
20005xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020006{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020007 xmlSchemaAttrInfoPtr iattr;
20008 /*
20009 * Grow/create list of attribute infos.
20010 */
20011 if (vctxt->attrInfos == NULL) {
20012 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20013 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
20014 vctxt->sizeAttrInfos = 1;
20015 if (vctxt->attrInfos == NULL) {
20016 xmlSchemaVErrMemory(vctxt,
20017 "allocating attribute info list", NULL);
20018 return (NULL);
20019 }
20020 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
20021 vctxt->sizeAttrInfos++;
20022 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20023 xmlRealloc(vctxt->attrInfos,
20024 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
20025 if (vctxt->attrInfos == NULL) {
20026 xmlSchemaVErrMemory(vctxt,
20027 "re-allocating attribute info list", NULL);
20028 return (NULL);
20029 }
20030 } else {
20031 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
20032 if (iattr->localName != NULL) {
20033 VERROR_INT("xmlSchemaGetFreshAttrInfo",
20034 "attr info not cleared");
20035 return (NULL);
20036 }
20037 iattr->nodeType = XML_ATTRIBUTE_NODE;
20038 return (iattr);
20039 }
20040 /*
20041 * Create an attribute info.
20042 */
20043 iattr = (xmlSchemaAttrInfoPtr)
20044 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20045 if (iattr == NULL) {
20046 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20047 return (NULL);
20048 }
20049 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20050 iattr->nodeType = XML_ATTRIBUTE_NODE;
20051 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20052
20053 return (iattr);
20054}
20055
20056static int
20057xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20058 xmlNodePtr attrNode,
20059 const xmlChar *localName,
20060 const xmlChar *nsName,
20061 int ownedNames,
20062 xmlChar *value,
20063 int ownedValue)
20064{
20065 xmlSchemaAttrInfoPtr attr;
20066
20067 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20068 if (attr == NULL) {
20069 VERROR_INT("xmlSchemaPushAttribute",
20070 "calling xmlSchemaGetFreshAttrInfo()");
20071 return (-1);
20072 }
20073 attr->node = attrNode;
20074 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20075 attr->localName = localName;
20076 attr->nsName = nsName;
20077 if (ownedNames)
20078 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20079 /*
20080 * Evaluate if it's an XSI attribute.
20081 */
20082 if (nsName != NULL) {
20083 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20084 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20085 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20086 }
20087 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20088 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20089 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20090 }
20091 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20092 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20093 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20094 }
20095 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20096 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20097 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20098 }
20099 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20100 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20101 }
20102 }
20103 attr->value = value;
20104 if (ownedValue)
20105 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20106 if (attr->metaType != 0)
20107 attr->state = XML_SCHEMAS_ATTR_META;
20108 return (0);
20109}
20110
20111static void
20112xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20113{
20114 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20115 FREE_AND_NULL(ielem->localName);
20116 FREE_AND_NULL(ielem->nsName);
20117 } else {
20118 ielem->localName = NULL;
20119 ielem->nsName = NULL;
20120 }
20121 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20122 FREE_AND_NULL(ielem->value);
20123 } else {
20124 ielem->value = NULL;
20125 }
20126 if (ielem->val != NULL) {
20127 xmlSchemaFreeValue(ielem->val);
20128 ielem->val = NULL;
20129 }
20130 if (ielem->idcMatchers != NULL) {
20131 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20132 ielem->idcMatchers = NULL;
20133 }
20134 if (ielem->idcTable != NULL) {
20135 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20136 ielem->idcTable = NULL;
20137 }
20138 if (ielem->regexCtxt != NULL) {
20139 xmlRegFreeExecCtxt(ielem->regexCtxt);
20140 ielem->regexCtxt = NULL;
20141 }
20142 if (ielem->nsBindings != NULL) {
20143 xmlFree((xmlChar **)ielem->nsBindings);
20144 ielem->nsBindings = NULL;
20145 ielem->nbNsBindings = 0;
20146 ielem->sizeNsBindings = 0;
20147 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020148}
20149
20150/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020151 * xmlSchemaGetFreshElemInfo:
20152 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020153 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020154 * Creates/reuses and initializes the element info item for
20155 * the currect tree depth.
20156 *
20157 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020158 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020159static xmlSchemaNodeInfoPtr
20160xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020161{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020162 xmlSchemaNodeInfoPtr info = NULL;
20163
20164 if (vctxt->depth > vctxt->sizeElemInfos) {
20165 VERROR_INT("xmlSchemaGetFreshElemInfo",
20166 "inconsistent depth encountered");
20167 return (NULL);
20168 }
20169 if (vctxt->elemInfos == NULL) {
20170 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20171 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20172 if (vctxt->elemInfos == NULL) {
20173 xmlSchemaVErrMemory(vctxt,
20174 "allocating the element info array", NULL);
20175 return (NULL);
20176 }
20177 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20178 vctxt->sizeElemInfos = 10;
20179 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20180 int i = vctxt->sizeElemInfos;
20181
20182 vctxt->sizeElemInfos *= 2;
20183 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20184 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20185 sizeof(xmlSchemaNodeInfoPtr));
20186 if (vctxt->elemInfos == NULL) {
20187 xmlSchemaVErrMemory(vctxt,
20188 "re-allocating the element info array", NULL);
20189 return (NULL);
20190 }
20191 /*
20192 * We need the new memory to be NULLed.
20193 * TODO: Use memset instead?
20194 */
20195 for (; i < vctxt->sizeElemInfos; i++)
20196 vctxt->elemInfos[i] = NULL;
20197 } else
20198 info = vctxt->elemInfos[vctxt->depth];
20199
20200 if (info == NULL) {
20201 info = (xmlSchemaNodeInfoPtr)
20202 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20203 if (info == NULL) {
20204 xmlSchemaVErrMemory(vctxt,
20205 "allocating an element info", NULL);
20206 return (NULL);
20207 }
20208 vctxt->elemInfos[vctxt->depth] = info;
20209 } else {
20210 if (info->localName != NULL) {
20211 VERROR_INT("xmlSchemaGetFreshElemInfo",
20212 "elem info has not been cleared");
20213 return (NULL);
20214 }
20215 }
20216 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20217 info->nodeType = XML_ELEMENT_NODE;
20218 info->depth = vctxt->depth;
20219
20220 return (info);
20221}
20222
20223#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20224#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20225#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20226
20227static int
20228xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20229 xmlNodePtr node,
20230 xmlSchemaTypePtr type,
20231 xmlSchemaValType valType,
20232 const xmlChar * value,
20233 xmlSchemaValPtr val,
20234 unsigned long length,
20235 int fireErrors)
20236{
20237 int ret, error = 0;
20238
20239 xmlSchemaTypePtr tmpType;
20240 xmlSchemaFacetLinkPtr facetLink;
20241 xmlSchemaFacetPtr facet;
20242 unsigned long len = 0;
20243 xmlSchemaWhitespaceValueType ws;
20244
20245 /*
20246 * In Libxml2, derived built-in types have currently no explicit facets.
20247 */
20248 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020249 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020250
20251 /*
20252 * NOTE: Do not jump away, if the facetSet of the given type is
20253 * empty: until now, "pattern" and "enumeration" facets of the
20254 * *base types* need to be checked as well.
20255 */
20256 if (type->facetSet == NULL)
20257 goto pattern_and_enum;
20258
20259 if (! VARIETY_ATOMIC(type)) {
20260 if (VARIETY_LIST(type))
20261 goto variety_list;
20262 else
20263 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020264 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020265 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020266 * Whitespace handling is only of importance for string-based
20267 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020268 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020269 tmpType = xmlSchemaGetPrimitiveType(type);
20270 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20271 IS_ANY_SIMPLE_TYPE(tmpType)) {
20272 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20273 } else
20274 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20275 /*
20276 * If the value was not computed (for string or
20277 * anySimpleType based types), then use the provided
20278 * type.
20279 */
20280 if (val == NULL)
20281 valType = valType;
20282 else
20283 valType = xmlSchemaGetValType(val);
20284
20285 ret = 0;
20286 for (facetLink = type->facetSet; facetLink != NULL;
20287 facetLink = facetLink->next) {
20288 /*
20289 * Skip the pattern "whiteSpace": it is used to
20290 * format the character content beforehand.
20291 */
20292 switch (facetLink->facet->type) {
20293 case XML_SCHEMA_FACET_WHITESPACE:
20294 case XML_SCHEMA_FACET_PATTERN:
20295 case XML_SCHEMA_FACET_ENUMERATION:
20296 continue;
20297 case XML_SCHEMA_FACET_LENGTH:
20298 case XML_SCHEMA_FACET_MINLENGTH:
20299 case XML_SCHEMA_FACET_MAXLENGTH:
20300 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20301 valType, value, val, &len, ws);
20302 break;
20303 default:
20304 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20305 valType, value, val, ws);
20306 break;
20307 }
20308 if (ret < 0) {
20309 AERROR_INT("xmlSchemaValidateFacets",
20310 "validating against a atomic type facet");
20311 return (-1);
20312 } else if (ret > 0) {
20313 if (fireErrors)
20314 xmlSchemaFacetErr(actxt, ret, node,
20315 value, len, type, facetLink->facet, NULL, NULL, NULL);
20316 else
20317 return (ret);
20318 if (error == 0)
20319 error = ret;
20320 }
20321 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020322 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020323
20324variety_list:
20325 if (! VARIETY_LIST(type))
20326 goto pattern_and_enum;
20327 /*
20328 * "length", "minLength" and "maxLength" of list types.
20329 */
20330 ret = 0;
20331 for (facetLink = type->facetSet; facetLink != NULL;
20332 facetLink = facetLink->next) {
20333
20334 switch (facetLink->facet->type) {
20335 case XML_SCHEMA_FACET_LENGTH:
20336 case XML_SCHEMA_FACET_MINLENGTH:
20337 case XML_SCHEMA_FACET_MAXLENGTH:
20338 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20339 value, length, NULL);
20340 break;
20341 default:
20342 continue;
20343 }
20344 if (ret < 0) {
20345 AERROR_INT("xmlSchemaValidateFacets",
20346 "validating against a list type facet");
20347 return (-1);
20348 } else if (ret > 0) {
20349 if (fireErrors)
20350 xmlSchemaFacetErr(actxt, ret, node,
20351 value, length, type, facetLink->facet, NULL, NULL, NULL);
20352 else
20353 return (ret);
20354 if (error == 0)
20355 error = ret;
20356 }
20357 ret = 0;
20358 }
20359
20360pattern_and_enum:
20361 if (error >= 0) {
20362 int found = 0;
20363 /*
20364 * Process enumerations. Facet values are in the value space
20365 * of the defining type's base type. This seems to be a bug in the
20366 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20367 * Only the first set of enumerations in the ancestor-or-self axis
20368 * is used for validation.
20369 */
20370 ret = 0;
20371 tmpType = type;
20372 do {
20373 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20374 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20375 continue;
20376 found = 1;
20377 ret = xmlSchemaAreValuesEqual(facet->val, val);
20378 if (ret == 1)
20379 break;
20380 else if (ret < 0) {
20381 AERROR_INT("xmlSchemaValidateFacets",
20382 "validating against an enumeration facet");
20383 return (-1);
20384 }
20385 }
20386 if (ret != 0)
20387 break;
20388 tmpType = tmpType->baseType;
20389 } while ((tmpType != NULL) &&
20390 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20391 if (found && (ret == 0)) {
20392 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20393 if (fireErrors) {
20394 xmlSchemaFacetErr(actxt, ret, node,
20395 value, 0, type, NULL, NULL, NULL, NULL);
20396 } else
20397 return (ret);
20398 if (error == 0)
20399 error = ret;
20400 }
20401 }
20402
20403 if (error >= 0) {
20404 int found;
20405 /*
20406 * Process patters. Pattern facets are ORed at type level
20407 * and ANDed if derived. Walk the base type axis.
20408 */
20409 tmpType = type;
20410 facet = NULL;
20411 do {
20412 found = 0;
20413 for (facetLink = tmpType->facetSet; facetLink != NULL;
20414 facetLink = facetLink->next) {
20415 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20416 continue;
20417 found = 1;
20418 /*
20419 * NOTE that for patterns, @value needs to be the
20420 * normalized vaule.
20421 */
20422 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20423 if (ret == 1)
20424 break;
20425 else if (ret < 0) {
20426 AERROR_INT("xmlSchemaValidateFacets",
20427 "validating against a pattern facet");
20428 return (-1);
20429 } else {
20430 /*
20431 * Save the last non-validating facet.
20432 */
20433 facet = facetLink->facet;
20434 }
20435 }
20436 if (found && (ret != 1)) {
20437 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20438 if (fireErrors) {
20439 xmlSchemaFacetErr(actxt, ret, node,
20440 value, 0, type, facet, NULL, NULL, NULL);
20441 } else
20442 return (ret);
20443 if (error == 0)
20444 error = ret;
20445 break;
20446 }
20447 tmpType = tmpType->baseType;
20448 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20449 }
20450
20451 return (error);
20452}
20453
20454static xmlChar *
20455xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20456 const xmlChar *value)
20457{
20458 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20459 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20460 return (xmlSchemaCollapseString(value));
20461 case XML_SCHEMA_WHITESPACE_REPLACE:
20462 return (xmlSchemaWhiteSpaceReplace(value));
20463 default:
20464 return (NULL);
20465 }
20466}
20467
20468static int
20469xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20470 const xmlChar *value,
20471 xmlSchemaValPtr *val,
20472 int valNeeded)
20473{
20474 int ret;
20475 const xmlChar *nsName;
20476 xmlChar *local, *prefix = NULL;
20477
20478 ret = xmlValidateQName(value, 1);
20479 if (ret != 0) {
20480 if (ret == -1) {
20481 VERROR_INT("xmlSchemaValidateQName",
20482 "calling xmlValidateQName()");
20483 return (-1);
20484 }
20485 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20486 }
20487 /*
20488 * NOTE: xmlSplitQName2 will always return a duplicated
20489 * strings.
20490 */
20491 local = xmlSplitQName2(value, &prefix);
20492 if (local == NULL)
20493 local = xmlStrdup(value);
20494 /*
20495 * OPTIMIZE TODO: Use flags for:
20496 * - is there any namespace binding?
20497 * - is there a default namespace?
20498 */
20499 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20500
20501 if (prefix != NULL) {
20502 xmlFree(prefix);
20503 /*
20504 * A namespace must be found if the prefix is
20505 * NOT NULL.
20506 */
20507 if (nsName == NULL) {
20508 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20509 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20510 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20511 "The QName value '%s' has no "
20512 "corresponding namespace declaration in "
20513 "scope", value, NULL);
20514 if (local != NULL)
20515 xmlFree(local);
20516 return (ret);
20517 }
20518 }
20519 if (valNeeded && val) {
20520 if (nsName != NULL)
20521 *val = xmlSchemaNewQNameValue(
20522 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20523 else
20524 *val = xmlSchemaNewQNameValue(NULL,
20525 BAD_CAST local);
20526 } else
20527 xmlFree(local);
20528 return (0);
20529}
20530
20531/*
20532* cvc-simple-type
20533*/
20534static int
20535xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20536 xmlNodePtr node,
20537 xmlSchemaTypePtr type,
20538 const xmlChar *value,
20539 xmlSchemaValPtr *retVal,
20540 int fireErrors,
20541 int normalize,
20542 int isNormalized)
20543{
20544 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20545 xmlSchemaValPtr val = NULL;
20546 xmlSchemaWhitespaceValueType ws;
20547 xmlChar *normValue = NULL;
20548
20549#define NORMALIZE(atype) \
20550 if ((! isNormalized) && \
20551 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20552 normValue = xmlSchemaNormalizeValue(atype, value); \
20553 if (normValue != NULL) \
20554 value = normValue; \
20555 isNormalized = 1; \
20556 }
20557
20558 if ((retVal != NULL) && (*retVal != NULL)) {
20559 xmlSchemaFreeValue(*retVal);
20560 *retVal = NULL;
20561 }
20562 /*
20563 * 3.14.4 Simple Type Definition Validation Rules
20564 * Validation Rule: String Valid
20565 */
20566 /*
20567 * 1 It is schema-valid with respect to that definition as defined
20568 * by Datatype Valid in [XML Schemas: Datatypes].
20569 */
20570 /*
20571 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20572 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20573 * the string must be a ·declared entity name·.
20574 */
20575 /*
20576 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20577 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20578 * then every whitespace-delimited substring of the string must be a ·declared
20579 * entity name·.
20580 */
20581 /*
20582 * 2.3 otherwise no further condition applies.
20583 */
20584 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20585 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020586 if (value == NULL)
20587 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020588 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20589 xmlSchemaTypePtr biType; /* The built-in type. */
20590 /*
20591 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20592 * a literal in the ·lexical space· of {base type definition}"
20593 */
20594 /*
20595 * Whitespace-normalize.
20596 */
20597 NORMALIZE(type);
20598 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20599 /*
20600 * Get the built-in type.
20601 */
20602 biType = type->baseType;
20603 while ((biType != NULL) &&
20604 (biType->type != XML_SCHEMA_TYPE_BASIC))
20605 biType = biType->baseType;
20606
20607 if (biType == NULL) {
20608 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20609 "could not get the built-in type");
20610 goto internal_error;
20611 }
20612 } else
20613 biType = type;
20614 /*
20615 * NOTATIONs need to be processed here, since they need
20616 * to lookup in the hashtable of NOTATION declarations of the schema.
20617 */
20618 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20619 switch (biType->builtInType) {
20620 case XML_SCHEMAS_NOTATION:
20621 ret = xmlSchemaValidateNotation(
20622 (xmlSchemaValidCtxtPtr) actxt,
20623 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20624 NULL, value, &val, valNeeded);
20625 break;
20626 case XML_SCHEMAS_QNAME:
20627 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20628 value, &val, valNeeded);
20629 break;
20630 default:
20631 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20632 if (valNeeded)
20633 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20634 value, &val, NULL);
20635 else
20636 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20637 value, NULL, NULL);
20638 break;
20639 }
20640 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20641 switch (biType->builtInType) {
20642 case XML_SCHEMAS_NOTATION:
20643 ret = xmlSchemaValidateNotation(NULL,
20644 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20645 value, &val, valNeeded);
20646 break;
20647 default:
20648 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20649 if (valNeeded)
20650 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20651 value, &val, node);
20652 else
20653 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20654 value, NULL, node);
20655 break;
20656 }
20657 } else {
20658 /*
20659 * Validation via a public API is not implemented yet.
20660 */
20661 TODO
20662 goto internal_error;
20663 }
20664 if (ret != 0) {
20665 if (ret < 0) {
20666 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20667 "validating against a built-in type");
20668 goto internal_error;
20669 }
20670 if (VARIETY_LIST(type))
20671 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20672 else
20673 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20674 }
20675 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20676 /*
20677 * Check facets.
20678 */
20679 ret = xmlSchemaValidateFacets(actxt, node, type,
20680 (xmlSchemaValType) biType->builtInType, value, val,
20681 0, fireErrors);
20682 if (ret != 0) {
20683 if (ret < 0) {
20684 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20685 "validating facets of atomic simple type");
20686 goto internal_error;
20687 }
20688 if (VARIETY_LIST(type))
20689 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20690 else
20691 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20692 }
20693 }
20694 if (fireErrors && (ret > 0))
20695 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20696 } else if (VARIETY_LIST(type)) {
20697
20698 xmlSchemaTypePtr itemType;
20699 const xmlChar *cur, *end;
20700 xmlChar *tmpValue = NULL;
20701 unsigned long len = 0;
20702 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20703 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20704 * of white space separated tokens, each of which ·match·es a literal
20705 * in the ·lexical space· of {item type definition}
20706 */
20707 /*
20708 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20709 * the list type has an enum or pattern facet.
20710 */
20711 NORMALIZE(type);
20712 /*
20713 * VAL TODO: Optimize validation of empty values.
20714 * VAL TODO: We do not have computed values for lists.
20715 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020716 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020717 cur = value;
20718 do {
20719 while (IS_BLANK_CH(*cur))
20720 cur++;
20721 end = cur;
20722 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20723 end++;
20724 if (end == cur)
20725 break;
20726 tmpValue = xmlStrndup(cur, end - cur);
20727 len++;
20728
20729 if (valNeeded)
20730 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20731 tmpValue, &curVal, fireErrors, 0, 1);
20732 else
20733 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20734 tmpValue, NULL, fireErrors, 0, 1);
20735 FREE_AND_NULL(tmpValue);
20736 if (curVal != NULL) {
20737 /*
20738 * Add to list of computed values.
20739 */
20740 if (val == NULL)
20741 val = curVal;
20742 else
20743 xmlSchemaValueAppend(prevVal, curVal);
20744 prevVal = curVal;
20745 curVal = NULL;
20746 }
20747 if (ret != 0) {
20748 if (ret < 0) {
20749 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20750 "validating an item of list simple type");
20751 goto internal_error;
20752 }
20753 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20754 break;
20755 }
20756 cur = end;
20757 } while (*cur != 0);
20758 FREE_AND_NULL(tmpValue);
20759 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20760 /*
20761 * Apply facets (pattern, enumeration).
20762 */
20763 ret = xmlSchemaValidateFacets(actxt, node, type,
20764 XML_SCHEMAS_UNKNOWN, value, val,
20765 len, fireErrors);
20766 if (ret != 0) {
20767 if (ret < 0) {
20768 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20769 "validating facets of list simple type");
20770 goto internal_error;
20771 }
20772 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20773 }
20774 }
20775 if (fireErrors && (ret > 0)) {
20776 /*
20777 * Report the normalized value.
20778 */
20779 normalize = 1;
20780 NORMALIZE(type);
20781 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20782 }
20783 } else if (VARIETY_UNION(type)) {
20784 xmlSchemaTypeLinkPtr memberLink;
20785 /*
20786 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20787 * not apply directly; however, the normalization behavior of ·union·
20788 * types is controlled by the value of whiteSpace on that one of the
20789 * ·memberTypes· against which the ·union· is successfully validated.
20790 *
20791 * This means that the value is normalized by the first validating
20792 * member type, then the facets of the union type are applied. This
20793 * needs changing of the value!
20794 */
20795
20796 /*
20797 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20798 * literal in the ·lexical space· of at least one member of
20799 * {member type definitions}
20800 */
20801 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20802 if (memberLink == NULL) {
20803 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20804 "union simple type has no member types");
20805 goto internal_error;
20806 }
20807 /*
20808 * Always normalize union type values, since we currently
20809 * cannot store the whitespace information with the value
20810 * itself; otherwise a later value-comparison would be
20811 * not possible.
20812 */
20813 while (memberLink != NULL) {
20814 if (valNeeded)
20815 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20816 memberLink->type, value, &val, 0, 1, 0);
20817 else
20818 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20819 memberLink->type, value, NULL, 0, 1, 0);
20820 if (ret <= 0)
20821 break;
20822 memberLink = memberLink->next;
20823 }
20824 if (ret != 0) {
20825 if (ret < 0) {
20826 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20827 "validating members of union simple type");
20828 goto internal_error;
20829 }
20830 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20831 }
20832 /*
20833 * Apply facets (pattern, enumeration).
20834 */
20835 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20836 /*
20837 * The normalization behavior of ·union· types is controlled by
20838 * the value of whiteSpace on that one of the ·memberTypes·
20839 * against which the ·union· is successfully validated.
20840 */
20841 NORMALIZE(memberLink->type);
20842 ret = xmlSchemaValidateFacets(actxt, node, type,
20843 XML_SCHEMAS_UNKNOWN, value, val,
20844 0, fireErrors);
20845 if (ret != 0) {
20846 if (ret < 0) {
20847 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20848 "validating facets of union simple type");
20849 goto internal_error;
20850 }
20851 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20852 }
20853 }
20854 if (fireErrors && (ret > 0))
20855 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20856 }
20857
20858 if (normValue != NULL)
20859 xmlFree(normValue);
20860 if (ret == 0) {
20861 if (retVal != NULL)
20862 *retVal = val;
20863 else if (val != NULL)
20864 xmlSchemaFreeValue(val);
20865 } else if (val != NULL)
20866 xmlSchemaFreeValue(val);
20867 return (ret);
20868internal_error:
20869 if (normValue != NULL)
20870 xmlFree(normValue);
20871 if (val != NULL)
20872 xmlSchemaFreeValue(val);
20873 return (-1);
20874}
20875
20876static int
20877xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20878 const xmlChar *value,
20879 const xmlChar **nsName,
20880 const xmlChar **localName)
20881{
20882 int ret = 0;
20883
20884 if ((nsName == NULL) || (localName == NULL))
20885 return (-1);
20886 *nsName = NULL;
20887 *localName = NULL;
20888
20889 ret = xmlValidateQName(value, 1);
20890 if (ret == -1)
20891 return (-1);
20892 if (ret > 0) {
20893 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20894 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20895 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20896 return (1);
20897 }
20898 {
20899 xmlChar *local = NULL;
20900 xmlChar *prefix;
20901
20902 /*
20903 * NOTE: xmlSplitQName2 will return a duplicated
20904 * string.
20905 */
20906 local = xmlSplitQName2(value, &prefix);
20907 VAL_CREATE_DICT;
20908 if (local == NULL)
20909 *localName = xmlDictLookup(vctxt->dict, value, -1);
20910 else {
20911 *localName = xmlDictLookup(vctxt->dict, local, -1);
20912 xmlFree(local);
20913 }
20914
20915 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20916
20917 if (prefix != NULL) {
20918 xmlFree(prefix);
20919 /*
20920 * A namespace must be found if the prefix is NOT NULL.
20921 */
20922 if (*nsName == NULL) {
20923 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20924 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20925 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20926 "The QName value '%s' has no "
20927 "corresponding namespace declaration in scope",
20928 value, NULL);
20929 return (2);
20930 }
20931 }
20932 }
20933 return (0);
20934}
20935
20936static int
20937xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20938 xmlSchemaAttrInfoPtr iattr,
20939 xmlSchemaTypePtr *localType,
20940 xmlSchemaElementPtr elemDecl)
20941{
20942 int ret = 0;
20943 /*
20944 * cvc-elt (3.3.4) : (4)
20945 * AND
20946 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20947 * (1.2.1.2.1) - (1.2.1.2.4)
20948 * Handle 'xsi:type'.
20949 */
20950 if (localType == NULL)
20951 return (-1);
20952 *localType = NULL;
20953 if (iattr == NULL)
20954 return (0);
20955 else {
20956 const xmlChar *nsName = NULL, *local = NULL;
20957 /*
20958 * TODO: We should report a *warning* that the type was overriden
20959 * by the instance.
20960 */
20961 ACTIVATE_ATTRIBUTE(iattr);
20962 /*
20963 * (cvc-elt) (3.3.4) : (4.1)
20964 * (cvc-assess-elt) (1.2.1.2.2)
20965 */
20966 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
20967 &nsName, &local);
20968 if (ret != 0) {
20969 if (ret < 0) {
20970 VERROR_INT("xmlSchemaValidateElementByDeclaration",
20971 "calling xmlSchemaQNameExpand() to validate the "
20972 "attribute 'xsi:type'");
20973 goto internal_error;
20974 }
20975 goto exit;
20976 }
20977 /*
20978 * (cvc-elt) (3.3.4) : (4.2)
20979 * (cvc-assess-elt) (1.2.1.2.3)
20980 */
20981 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
20982 if (*localType == NULL) {
20983 xmlChar *str = NULL;
20984
20985 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20986 XML_SCHEMAV_CVC_ELT_4_2, NULL,
20987 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20988 "The QName value '%s' of the xsi:type attribute does not "
20989 "resolve to a type definition",
20990 xmlSchemaFormatQName(&str, nsName, local), NULL);
20991 FREE_AND_NULL(str);
20992 ret = vctxt->err;
20993 goto exit;
20994 }
20995 if (elemDecl != NULL) {
20996 int set = 0;
20997
20998 /*
20999 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
21000 * "The ·local type definition· must be validly
21001 * derived from the {type definition} given the union of
21002 * the {disallowed substitutions} and the {type definition}'s
21003 * {prohibited substitutions}, as defined in
21004 * Type Derivation OK (Complex) (§3.4.6)
21005 * (if it is a complex type definition),
21006 * or given {disallowed substitutions} as defined in Type
21007 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21008 * definition)."
21009 *
21010 * {disallowed substitutions}: the "block" on the element decl.
21011 * {prohibited substitutions}: the "block" on the type def.
21012 */
21013 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21014 (elemDecl->subtypes->flags &
21015 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21016 set |= SUBSET_EXTENSION;
21017
21018 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21019 (elemDecl->subtypes->flags &
21020 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21021 set |= SUBSET_RESTRICTION;
21022
21023 if (xmlSchemaCheckCOSDerivedOK(*localType,
21024 elemDecl->subtypes, set) != 0) {
21025 xmlChar *str = NULL;
21026
21027 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21028 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
21029 "The type definition '%s', specified by xsi:type, is "
21030 "blocked or not validly derived from the type definition "
21031 "of the element declaration",
21032 xmlSchemaFormatQName(&str,
21033 (*localType)->targetNamespace,
21034 (*localType)->name),
21035 NULL);
21036 FREE_AND_NULL(str);
21037 ret = vctxt->err;
21038 *localType = NULL;
21039 }
21040 }
21041 }
21042exit:
21043 ACTIVATE_ELEM;
21044 return (ret);
21045internal_error:
21046 ACTIVATE_ELEM;
21047 return (-1);
21048}
21049
21050static int
21051xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21052{
21053 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21054 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21055
21056 /*
21057 * cvc-elt (3.3.4) : 1
21058 */
21059 if (elemDecl == NULL) {
21060 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21061 "No matching declaration available");
21062 return (vctxt->err);
21063 }
21064 /*
21065 * cvc-elt (3.3.4) : 2
21066 */
21067 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21068 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21069 "The element declaration is abstract");
21070 return (vctxt->err);
21071 }
21072 if (actualType == NULL) {
21073 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21074 "The type definition is absent");
21075 return (XML_SCHEMAV_CVC_TYPE_1);
21076 }
21077 if (vctxt->nbAttrInfos != 0) {
21078 int ret;
21079 xmlSchemaAttrInfoPtr iattr;
21080 /*
21081 * cvc-elt (3.3.4) : 3
21082 * Handle 'xsi:nil'.
21083 */
21084 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21085 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21086 if (iattr) {
21087 ACTIVATE_ATTRIBUTE(iattr);
21088 /*
21089 * Validate the value.
21090 */
21091 ret = xmlSchemaVCheckCVCSimpleType(
21092 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21093 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21094 iattr->value, &(iattr->val), 1, 0, 0);
21095 ACTIVATE_ELEM;
21096 if (ret < 0) {
21097 VERROR_INT("xmlSchemaValidateElemDecl",
21098 "calling xmlSchemaVCheckCVCSimpleType() to "
21099 "validate the attribute 'xsi:nil'");
21100 return (-1);
21101 }
21102 if (ret == 0) {
21103 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21104 /*
21105 * cvc-elt (3.3.4) : 3.1
21106 */
21107 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21108 "The element is not 'nillable'");
21109 /* Does not return an error on purpose. */
21110 } else {
21111 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21112 /*
21113 * cvc-elt (3.3.4) : 3.2.2
21114 */
21115 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21116 (elemDecl->value != NULL)) {
21117 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21118 "The element cannot be 'nilled' because "
21119 "there is a fixed value constraint defined "
21120 "for it");
21121 /* Does not return an error on purpose. */
21122 } else
21123 vctxt->inode->flags |=
21124 XML_SCHEMA_ELEM_INFO_NILLED;
21125 }
21126 }
21127 }
21128 }
21129 /*
21130 * cvc-elt (3.3.4) : 4
21131 * Handle 'xsi:type'.
21132 */
21133 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21134 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21135 if (iattr) {
21136 xmlSchemaTypePtr localType = NULL;
21137
21138 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21139 elemDecl);
21140 if (ret != 0) {
21141 if (ret == -1) {
21142 VERROR_INT("xmlSchemaValidateElemDecl",
21143 "calling xmlSchemaProcessXSIType() to "
21144 "process the attribute 'xsi:type'");
21145 return (-1);
21146 }
21147 /* Does not return an error on purpose. */
21148 }
21149 if (localType != NULL) {
21150 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21151 actualType = localType;
21152 }
21153 }
21154 }
21155 /*
21156 * IDC: Register identity-constraint XPath matchers.
21157 */
21158 if ((elemDecl->idcs != NULL) &&
21159 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21160 return (-1);
21161 /*
21162 * No actual type definition.
21163 */
21164 if (actualType == NULL) {
21165 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21166 "The type definition is absent");
21167 return (XML_SCHEMAV_CVC_TYPE_1);
21168 }
21169 /*
21170 * Remember the actual type definition.
21171 */
21172 vctxt->inode->typeDef = actualType;
21173
21174 return (0);
21175}
21176
21177static int
21178xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21179{
21180 xmlSchemaAttrInfoPtr iattr;
21181 int ret = 0, i;
21182
21183 /*
21184 * SPEC cvc-type (3.1.1)
21185 * "The attributes of must be empty, excepting those whose namespace
21186 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21187 * whose local name is one of type, nil, schemaLocation or
21188 * noNamespaceSchemaLocation."
21189 */
21190 if (vctxt->nbAttrInfos == 0)
21191 return (0);
21192 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21193 iattr = vctxt->attrInfos[i];
21194 if (! iattr->metaType) {
21195 ACTIVATE_ATTRIBUTE(iattr)
21196 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21197 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21198 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21199 }
21200 }
21201 ACTIVATE_ELEM
21202 return (ret);
21203}
21204
21205/*
21206* Cleanup currently used attribute infos.
21207*/
21208static void
21209xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21210{
21211 int i;
21212 xmlSchemaAttrInfoPtr attr;
21213
21214 if (vctxt->nbAttrInfos == 0)
21215 return;
21216 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21217 attr = vctxt->attrInfos[i];
21218 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21219 if (attr->localName != NULL)
21220 xmlFree((xmlChar *) attr->localName);
21221 if (attr->nsName != NULL)
21222 xmlFree((xmlChar *) attr->nsName);
21223 }
21224 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21225 if (attr->value != NULL)
21226 xmlFree((xmlChar *) attr->value);
21227 }
21228 if (attr->val != NULL) {
21229 xmlSchemaFreeValue(attr->val);
21230 attr->val = NULL;
21231 }
21232 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21233 }
21234 vctxt->nbAttrInfos = 0;
21235}
21236
21237/*
21238* 3.4.4 Complex Type Definition Validation Rules
21239* Element Locally Valid (Complex Type) (cvc-complex-type)
21240* 3.2.4 Attribute Declaration Validation Rules
21241* Validation Rule: Attribute Locally Valid (cvc-attribute)
21242* Attribute Locally Valid (Use) (cvc-au)
21243*
21244* Only "assessed" attribute information items will be visible to
21245* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21246*/
21247static int
21248xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21249{
21250 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21251 xmlSchemaAttributeLinkPtr attrUseLink;
21252 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21253 xmlSchemaAttrInfoPtr attr, tmpAttr;
21254 int i, found, nbAttrs;
21255 int xpathRes = 0, res, wildIDs = 0, fixed;
21256
21257 /*
21258 * SPEC (cvc-attribute)
21259 * (1) "The declaration must not be ·absent· (see Missing
21260 * Sub-components (§5.3) for how this can fail to be
21261 * the case)."
21262 * (2) "Its {type definition} must not be absent."
21263 *
21264 * NOTE (1) + (2): This is not handled here, since we currently do not
21265 * allow validation against schemas which have missing sub-components.
21266 *
21267 * SPEC (cvc-complex-type)
21268 * (3) "For each attribute information item in the element information
21269 * item's [attributes] excepting those whose [namespace name] is
21270 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21271 * [local name] is one of type, nil, schemaLocation or
21272 * noNamespaceSchemaLocation, the appropriate case among the following
21273 * must be true:
21274 *
21275 */
21276 nbAttrs = vctxt->nbAttrInfos;
21277 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21278 attrUseLink = attrUseLink->next) {
21279
21280 found = 0;
21281 attrUse = attrUseLink->attr;
21282 /*
21283 * VAL TODO: Implement a real "attribute use" component.
21284 */
21285 if (attrUse->refDecl != NULL)
21286 attrDecl = attrUse->refDecl;
21287 else
21288 attrDecl = attrUse;
21289 for (i = 0; i < nbAttrs; i++) {
21290 attr = vctxt->attrInfos[i];
21291 /*
21292 * SPEC (cvc-complex-type) (3)
21293 * Skip meta attributes.
21294 */
21295 if (attr->metaType)
21296 continue;
21297 if (attr->localName[0] != attrDecl->name[0])
21298 continue;
21299 if (!xmlStrEqual(attr->localName, attrDecl->name))
21300 continue;
21301 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21302 continue;
21303 found = 1;
21304 /*
21305 * SPEC (cvc-complex-type)
21306 * (3.1) "If there is among the {attribute uses} an attribute
21307 * use with an {attribute declaration} whose {name} matches
21308 * the attribute information item's [local name] and whose
21309 * {target namespace} is identical to the attribute information
21310 * item's [namespace name] (where an ·absent· {target namespace}
21311 * is taken to be identical to a [namespace name] with no value),
21312 * then the attribute information must be ·valid· with respect
21313 * to that attribute use as per Attribute Locally Valid (Use)
21314 * (§3.5.4). In this case the {attribute declaration} of that
21315 * attribute use is the ·context-determined declaration· for the
21316 * attribute information item with respect to Schema-Validity
21317 * Assessment (Attribute) (§3.2.4) and
21318 * Assessment Outcome (Attribute) (§3.2.5).
21319 */
21320 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21321 attr->use = attrUse;
21322 /*
21323 * Context-determined declaration.
21324 */
21325 attr->decl = attrDecl;
21326 attr->typeDef = attrDecl->subtypes;
21327 break;
21328 }
21329
21330 if (found)
21331 continue;
21332
21333 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21334 /*
21335 * Handle non-existent, required attributes.
21336 *
21337 * SPEC (cvc-complex-type)
21338 * (4) "The {attribute declaration} of each attribute use in
21339 * the {attribute uses} whose {required} is true matches one
21340 * of the attribute information items in the element information
21341 * item's [attributes] as per clause 3.1 above."
21342 */
21343 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21344 if (tmpAttr == NULL) {
21345 VERROR_INT(
21346 "xmlSchemaVAttributesComplex",
21347 "calling xmlSchemaGetFreshAttrInfo()");
21348 return (-1);
21349 }
21350 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21351 tmpAttr->use = attrUse;
21352 tmpAttr->decl = attrDecl;
21353 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21354 ((attrUse->defValue != NULL) ||
21355 (attrDecl->defValue != NULL))) {
21356 /*
21357 * Handle non-existent, optional, default/fixed attributes.
21358 */
21359 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21360 if (tmpAttr == NULL) {
21361 VERROR_INT(
21362 "xmlSchemaVAttributesComplex",
21363 "calling xmlSchemaGetFreshAttrInfo()");
21364 return (-1);
21365 }
21366 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21367 tmpAttr->use = attrUse;
21368 tmpAttr->decl = attrDecl;
21369 tmpAttr->typeDef = attrDecl->subtypes;
21370 tmpAttr->localName = attrDecl->name;
21371 tmpAttr->nsName = attrDecl->targetNamespace;
21372 }
21373 }
21374 if (vctxt->nbAttrInfos == 0)
21375 return (0);
21376 /*
21377 * Validate against the wildcard.
21378 */
21379 if (type->attributeWildcard != NULL) {
21380 /*
21381 * SPEC (cvc-complex-type)
21382 * (3.2.1) "There must be an {attribute wildcard}."
21383 */
21384 for (i = 0; i < nbAttrs; i++) {
21385 attr = vctxt->attrInfos[i];
21386 /*
21387 * SPEC (cvc-complex-type) (3)
21388 * Skip meta attributes.
21389 */
21390 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21391 continue;
21392 /*
21393 * SPEC (cvc-complex-type)
21394 * (3.2.2) "The attribute information item must be ·valid· with
21395 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21396 *
21397 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21398 * "... its [namespace name] must be ·valid· with respect to
21399 * the wildcard constraint, as defined in Wildcard allows
21400 * Namespace Name (§3.10.4)."
21401 */
21402 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21403 attr->nsName)) {
21404 /*
21405 * Handle processContents.
21406 *
21407 * SPEC (cvc-wildcard):
21408 * processContents | context-determined declaration:
21409 * "strict" "mustFind"
21410 * "lax" "none"
21411 * "skip" "skip"
21412 */
21413 if (type->attributeWildcard->processContents ==
21414 XML_SCHEMAS_ANY_SKIP) {
21415 /*
21416 * context-determined declaration = "skip"
21417 *
21418 * SPEC PSVI Assessment Outcome (Attribute)
21419 * [validity] = "notKnown"
21420 * [validation attempted] = "none"
21421 */
21422 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21423 continue;
21424 }
21425 /*
21426 * Find an attribute declaration.
21427 */
21428 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21429 attr->localName, attr->nsName);
21430 if (attr->decl != NULL) {
21431 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21432 /*
21433 * SPEC (cvc-complex-type)
21434 * (5) "Let [Definition:] the wild IDs be the set of
21435 * all attribute information item to which clause 3.2
21436 * applied and whose ·validation· resulted in a
21437 * ·context-determined declaration· of mustFind or no
21438 * ·context-determined declaration· at all, and whose
21439 * [local name] and [namespace name] resolve (as
21440 * defined by QName resolution (Instance) (§3.15.4)) to
21441 * an attribute declaration whose {type definition} is
21442 * or is derived from ID. Then all of the following
21443 * must be true:"
21444 */
21445 attr->typeDef = attr->decl->subtypes;
21446 if (xmlSchemaIsDerivedFromBuiltInType(
21447 attr->typeDef, XML_SCHEMAS_ID)) {
21448 /*
21449 * SPEC (5.1) "There must be no more than one
21450 * item in ·wild IDs·."
21451 */
21452 if (wildIDs != 0) {
21453 /* VAL TODO */
21454 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21455 TODO
21456 continue;
21457 }
21458 wildIDs++;
21459 /*
21460 * SPEC (cvc-complex-type)
21461 * (5.2) "If ·wild IDs· is non-empty, there must not
21462 * be any attribute uses among the {attribute uses}
21463 * whose {attribute declaration}'s {type definition}
21464 * is or is derived from ID."
21465 */
21466 for (attrUseLink = type->attributeUses;
21467 attrUseLink != NULL;
21468 attrUseLink = attrUseLink->next) {
21469 if (xmlSchemaIsDerivedFromBuiltInType(
21470 attrUseLink->attr->subtypes,
21471 XML_SCHEMAS_ID)) {
21472 /* VAL TODO */
21473 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21474 TODO
21475 }
21476 }
21477 }
21478 } else if (type->attributeWildcard->processContents ==
21479 XML_SCHEMAS_ANY_LAX) {
21480 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21481 /*
21482 * SPEC PSVI Assessment Outcome (Attribute)
21483 * [validity] = "notKnown"
21484 * [validation attempted] = "none"
21485 */
21486 } else {
21487 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21488 }
21489 }
21490 }
21491 }
21492
21493
21494 if (vctxt->nbAttrInfos == 0)
21495 return (0);
21496
21497 /*
21498 * Validate values, create default attributes, evaluate IDCs.
21499 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021500 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21501 attr = vctxt->attrInfos[i];
21502 /*
21503 * VAL TODO: Note that we won't try to resolve IDCs to
21504 * "lax" and "skip" validated attributes. Check what to
21505 * do in this case.
21506 */
21507 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21508 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21509 continue;
21510 /*
21511 * VAL TODO: What to do if the type definition is missing?
21512 */
21513 if (attr->typeDef == NULL) {
21514 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21515 continue;
21516 }
21517
21518 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021519 fixed = 0;
21520 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021521
21522 if (vctxt->xpathStates != NULL) {
21523 /*
21524 * Evaluate IDCs.
21525 */
21526 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21527 XML_ATTRIBUTE_NODE);
21528 if (xpathRes == -1) {
21529 VERROR_INT("xmlSchemaVAttributesComplex",
21530 "calling xmlSchemaXPathEvaluate()");
21531 goto internal_error;
21532 }
21533 }
21534
21535 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21536 /*
21537 * Default/fixed attributes.
21538 */
21539 if (xpathRes) {
21540 if (attr->use->defValue == NULL) {
21541 attr->value = (xmlChar *) attr->use->defValue;
21542 attr->val = attr->use->defVal;
21543 } else {
21544 attr->value = (xmlChar *) attr->decl->defValue;
21545 attr->val = attr->decl->defVal;
21546 }
21547 /*
21548 * IDCs will consume the precomputed default value,
21549 * so we need to clone it.
21550 */
21551 if (attr->val == NULL) {
21552 VERROR_INT("xmlSchemaVAttributesComplex",
21553 "default/fixed value on an attribute use was "
21554 "not precomputed");
21555 goto internal_error;
21556 }
21557 attr->val = xmlSchemaCopyValue(attr->val);
21558 if (attr->val == NULL) {
21559 VERROR_INT("xmlSchemaVAttributesComplex",
21560 "calling xmlSchemaCopyValue()");
21561 goto internal_error;
21562 }
21563 }
21564 /*
21565 * PSVI: Add the default attribute to the current element.
21566 * VAL TODO: Should we use the *normalized* value? This currently
21567 * uses the *initial* value.
21568 */
21569 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21570 (attr->node != NULL) && (attr->node->doc != NULL)) {
21571 xmlChar *normValue;
21572 const xmlChar *value;
21573
21574 value = attr->value;
21575 /*
21576 * Normalize the value.
21577 */
21578 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21579 attr->value);
21580 if (normValue != NULL)
21581 value = BAD_CAST normValue;
21582
21583 if (attr->nsName == NULL) {
21584 if (xmlNewProp(attr->node->parent,
21585 attr->localName, value) == NULL) {
21586 VERROR_INT("xmlSchemaVAttributesComplex",
21587 "callling xmlNewProp()");
21588 if (normValue != NULL)
21589 xmlFree(normValue);
21590 goto internal_error;
21591 }
21592 } else {
21593 xmlNsPtr ns;
21594
21595 ns = xmlSearchNsByHref(attr->node->doc,
21596 attr->node->parent, attr->nsName);
21597 if (ns == NULL) {
21598 xmlChar prefix[12];
21599 int counter = 0;
21600
21601 /*
21602 * Create a namespace declaration on the validation
21603 * root node if no namespace declaration is in scope.
21604 */
21605 do {
21606 snprintf((char *) prefix, 12, "p%d", counter++);
21607 ns = xmlSearchNs(attr->node->doc,
21608 attr->node->parent, BAD_CAST prefix);
21609 if (counter > 1000) {
21610 VERROR_INT(
21611 "xmlSchemaVAttributesComplex",
21612 "could not compute a ns prefix for a "
21613 "default/fixed attribute");
21614 if (normValue != NULL)
21615 xmlFree(normValue);
21616 goto internal_error;
21617 }
21618 } while (ns != NULL);
21619 ns = xmlNewNs(vctxt->validationRoot,
21620 attr->nsName, BAD_CAST prefix);
21621 }
21622 xmlNewNsProp(attr->node->parent, ns,
21623 attr->localName, value);
21624 }
21625 if (normValue != NULL)
21626 xmlFree(normValue);
21627 }
21628 /*
21629 * Go directly to IDC evaluation.
21630 */
21631 goto eval_idcs;
21632 }
21633 /*
21634 * Validate the value.
21635 */
21636 if (vctxt->value != NULL) {
21637 /*
21638 * Free last computed value; just for safety reasons.
21639 */
21640 xmlSchemaFreeValue(vctxt->value);
21641 vctxt->value = NULL;
21642 }
21643 /*
21644 * Note that the attribute *use* can be unavailable, if
21645 * the attribute was a wild attribute.
21646 */
21647 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21648 ((attr->use != NULL) &&
21649 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21650 fixed = 1;
21651 else
21652 fixed = 0;
21653 /*
21654 * SPEC (cvc-attribute)
21655 * (3) "The item's ·normalized value· must be locally ·valid·
21656 * with respect to that {type definition} as per
21657 * String Valid (§3.14.4)."
21658 *
21659 * VAL TODO: Do we already have the
21660 * "normalized attribute value" here?
21661 */
21662 if (xpathRes || fixed) {
21663 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21664 /*
21665 * Request a computed value.
21666 */
21667 res = xmlSchemaVCheckCVCSimpleType(
21668 (xmlSchemaAbstractCtxtPtr) vctxt,
21669 attr->node, attr->typeDef, attr->value, &(attr->val),
21670 1, 1, 0);
21671 } else {
21672 res = xmlSchemaVCheckCVCSimpleType(
21673 (xmlSchemaAbstractCtxtPtr) vctxt,
21674 attr->node, attr->typeDef, attr->value, NULL,
21675 1, 0, 0);
21676 }
21677
21678 if (res != 0) {
21679 if (res == -1) {
21680 VERROR_INT("xmlSchemaVAttributesComplex",
21681 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21682 goto internal_error;
21683 }
21684 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21685 /*
21686 * SPEC PSVI Assessment Outcome (Attribute)
21687 * [validity] = "invalid"
21688 */
21689 goto eval_idcs;
21690 }
21691
21692 if (fixed) {
21693 int ws;
21694 /*
21695 * SPEC Attribute Locally Valid (Use) (cvc-au)
21696 * "For an attribute information item to be·valid·
21697 * with respect to an attribute use its *normalized*
21698 * value· must match the *canonical* lexical
21699 * representation of the attribute use's {value
21700 * constraint}value, if it is present and fixed."
21701 *
21702 * VAL TODO: The requirement for the *canonical* value
21703 * will be removed in XML Schema 1.1.
21704 */
21705 /*
21706 * SPEC Attribute Locally Valid (cvc-attribute)
21707 * (4) "The item's *actual* value· must match the *value* of
21708 * the {value constraint}, if it is present and fixed."
21709 */
21710 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21711 if (attr->val == NULL) {
21712 /* VAL TODO: A value was not precomputed. */
21713 TODO
21714 goto eval_idcs;
21715 }
21716 if ((attr->use != NULL) &&
21717 (attr->use->defValue != NULL)) {
21718 if (attr->use->defVal == NULL) {
21719 /* VAL TODO: A default value was not precomputed. */
21720 TODO
21721 goto eval_idcs;
21722 }
21723 attr->vcValue = attr->use->defValue;
21724 /*
21725 if (xmlSchemaCompareValuesWhtsp(attr->val,
21726 (xmlSchemaWhitespaceValueType) ws,
21727 attr->use->defVal,
21728 (xmlSchemaWhitespaceValueType) ws) != 0) {
21729 */
21730 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21731 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21732 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021733 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021734 /* VAL TODO: A default value was not precomputed. */
21735 TODO
21736 goto eval_idcs;
21737 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021738 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021739 /*
21740 if (xmlSchemaCompareValuesWhtsp(attr->val,
21741 (xmlSchemaWhitespaceValueType) ws,
21742 attrDecl->defVal,
21743 (xmlSchemaWhitespaceValueType) ws) != 0) {
21744 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021745 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021746 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21747 }
21748 /*
21749 * [validity] = "valid"
21750 */
21751 }
21752eval_idcs:
21753 /*
21754 * Evaluate IDCs.
21755 */
21756 if (xpathRes) {
21757 if (xmlSchemaXPathProcessHistory(vctxt,
21758 vctxt->depth +1) == -1) {
21759 VERROR_INT("xmlSchemaVAttributesComplex",
21760 "calling xmlSchemaXPathEvaluate()");
21761 goto internal_error;
21762 }
21763 }
21764 }
21765
21766 /*
21767 * Report errors.
21768 */
21769 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21770 attr = vctxt->attrInfos[i];
21771 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21772 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21773 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21774 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21775 continue;
21776 ACTIVATE_ATTRIBUTE(attr);
21777 switch (attr->state) {
21778 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21779 xmlChar *str = NULL;
21780 ACTIVATE_ELEM;
21781 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21782 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21783 "The attribute '%s' is required but missing",
21784 xmlSchemaFormatQName(&str,
21785 attr->decl->targetNamespace,
21786 attr->decl->name),
21787 NULL);
21788 FREE_AND_NULL(str)
21789 break;
21790 }
21791 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21792 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21793 "The type definition is absent");
21794 break;
21795 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21796 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21797 XML_SCHEMAV_CVC_AU, NULL, NULL,
21798 "The value '%s' does not match the fixed "
21799 "value constraint '%s'",
21800 attr->value, attr->vcValue);
21801 break;
21802 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21803 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21804 "No matching global attribute declaration available, but "
21805 "demanded by the strict wildcard");
21806 break;
21807 case XML_SCHEMAS_ATTR_UNKNOWN:
21808 if (attr->metaType)
21809 break;
21810 /*
21811 * MAYBE VAL TODO: One might report different error messages
21812 * for the following errors.
21813 */
21814 if (type->attributeWildcard == NULL) {
21815 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21816 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21817 } else {
21818 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21819 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21820 }
21821 break;
21822 default:
21823 break;
21824 }
21825 }
21826
21827 ACTIVATE_ELEM;
21828 return (0);
21829internal_error:
21830 ACTIVATE_ELEM;
21831 return (-1);
21832}
21833
21834static int
21835xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21836 int *skip)
21837{
21838 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21839 /*
21840 * The namespace of the element was already identified to be
21841 * matching the wildcard.
21842 */
21843 if ((skip == NULL) || (wild == NULL) ||
21844 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21845 VERROR_INT("xmlSchemaValidateElemWildcard",
21846 "bad arguments");
21847 return (-1);
21848 }
21849 *skip = 0;
21850 if (wild->negNsSet != NULL) {
21851 /*
21852 * URGENT VAL TODO: Fix the content model to reject
21853 * "##other" wildcards.
21854 */
21855 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21856 vctxt->inode->nsName) != 0) {
21857 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21858 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21859 /*
21860 * VAL TODO: Workaround possible *only* if minOccurs and
21861 * maxOccurs are 1.
21862 */
21863 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21864 /* VAL TODO: error code? */
21865 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21866 (xmlSchemaTypePtr) wild,
21867 "This element is not accepted by the wildcard",
21868 0, 0, NULL);
21869 vctxt->skipDepth = vctxt->depth;
21870 if ((pinode->flags &
21871 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21872 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21873 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21874 return (XML_SCHEMAV_ELEMENT_CONTENT);
21875 }
21876 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21877 *skip = 1;
21878 return (0);
21879 }
21880 vctxt->inode->typeDef =
21881 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21882 return (0);
21883 }
21884 }
21885 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21886 /*
21887 * URGENT VAL TODO: Either we need to position the stream to the
21888 * next sibling, or walk the whole subtree.
21889 */
21890 *skip = 1;
21891 return (0);
21892 }
21893 {
21894 xmlSchemaElementPtr decl = NULL;
21895
21896 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21897 vctxt->inode->localName, vctxt->inode->nsName,
21898 NULL);
21899 if (decl != NULL) {
21900 vctxt->inode->decl = decl;
21901 return (0);
21902 }
21903 }
21904 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21905 /* VAL TODO: Change to proper error code. */
21906 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21907 "No matching global element declaration available, but "
21908 "demanded by the strict wildcard");
21909 return (vctxt->err);
21910 }
21911 if (vctxt->nbAttrInfos != 0) {
21912 xmlSchemaAttrInfoPtr iattr;
21913 /*
21914 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21915 * (1.2.1.2.1) - (1.2.1.2.3 )
21916 *
21917 * Use the xsi:type attribute for the type definition.
21918 */
21919 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21920 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21921 if (iattr != NULL) {
21922 if (xmlSchemaProcessXSIType(vctxt, iattr,
21923 &(vctxt->inode->typeDef), NULL) == -1) {
21924 VERROR_INT("xmlSchemaValidateElemWildcard",
21925 "calling xmlSchemaProcessXSIType() to "
21926 "process the attribute 'xsi:nil'");
21927 return (-1);
21928 }
21929 /*
21930 * Don't return an error on purpose.
21931 */
21932 return (0);
21933 }
21934 }
21935 /*
21936 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21937 *
21938 * Fallback to "anyType".
21939 */
21940 vctxt->inode->typeDef =
21941 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21942 return (0);
21943}
21944
21945/*
21946* xmlSchemaCheckCOSValidDefault:
21947*
21948* This will be called if: not nilled, no content and a default/fixed
21949* value is provided.
21950*/
21951
21952static int
21953xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
21954 const xmlChar *value,
21955 xmlSchemaValPtr *val)
21956{
21957 int ret = 0;
21958 xmlSchemaNodeInfoPtr inode = vctxt->inode;
21959
21960 /*
21961 * cos-valid-default:
21962 * Schema Component Constraint: Element Default Valid (Immediate)
21963 * For a string to be a valid default with respect to a type
21964 * definition the appropriate case among the following must be true:
21965 */
21966 if IS_COMPLEX_TYPE(inode->typeDef) {
21967 /*
21968 * Complex type.
21969 *
21970 * SPEC (2.1) "its {content type} must be a simple type definition
21971 * or mixed."
21972 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
21973 * type}'s particle must be ·emptiable· as defined by
21974 * Particle Emptiable (§3.9.6)."
21975 */
21976 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
21977 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
21978 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
21979 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
21980 /* NOTE that this covers (2.2.2) as well. */
21981 VERROR(ret, NULL,
21982 "For a string to be a valid default, the type definition "
21983 "must be a simple type or a complex type with simple content "
21984 "or mixed content and a particle emptiable");
21985 return(ret);
21986 }
21987 }
21988 /*
21989 * 1 If the type definition is a simple type definition, then the string
21990 * must be ·valid· with respect to that definition as defined by String
21991 * Valid (§3.14.4).
21992 *
21993 * AND
21994 *
21995 * 2.2.1 If the {content type} is a simple type definition, then the
21996 * string must be ·valid· with respect to that simple type definition
21997 * as defined by String Valid (§3.14.4).
21998 */
21999 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22000
22001 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22002 NULL, inode->typeDef, value, val, 1, 1, 0);
22003
22004 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22005
22006 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22007 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
22008 }
22009 if (ret < 0) {
22010 VERROR_INT("xmlSchemaCheckCOSValidDefault",
22011 "calling xmlSchemaVCheckCVCSimpleType()");
22012 }
22013 return (ret);
22014}
22015
22016static void
22017xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22018 const xmlChar * name ATTRIBUTE_UNUSED,
22019 xmlSchemaElementPtr item,
22020 xmlSchemaNodeInfoPtr inode)
22021{
22022 inode->decl = item;
22023#ifdef DEBUG_CONTENT
22024 {
22025 xmlChar *str = NULL;
22026
22027 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
22028 xmlGenericError(xmlGenericErrorContext,
22029 "AUTOMATON callback for '%s' [declaration]\n",
22030 xmlSchemaFormatQName(&str,
22031 inode->localName, inode->nsName));
22032 } else {
22033 xmlGenericError(xmlGenericErrorContext,
22034 "AUTOMATON callback for '%s' [wildcard]\n",
22035 xmlSchemaFormatQName(&str,
22036 inode->localName, inode->nsName));
22037
22038 }
22039 FREE_AND_NULL(str)
22040 }
22041#endif
22042}
22043
22044static int
22045xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022046{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022047 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22048 if (vctxt->inode == NULL) {
22049 VERROR_INT("xmlSchemaValidatorPushElem",
22050 "calling xmlSchemaGetFreshElemInfo()");
22051 return (-1);
22052 }
22053 vctxt->nbAttrInfos = 0;
22054 return (0);
22055}
22056
22057static int
22058xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22059 xmlSchemaNodeInfoPtr inode,
22060 xmlSchemaTypePtr type,
22061 const xmlChar *value)
22062{
22063 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22064 return (xmlSchemaVCheckCVCSimpleType(
22065 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22066 type, value, &(inode->val), 1, 1, 0));
22067 else
22068 return (xmlSchemaVCheckCVCSimpleType(
22069 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22070 type, value, NULL, 1, 0, 0));
22071}
22072
22073
22074
22075/*
22076* Process END of element.
22077*/
22078static int
22079xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22080{
22081 int ret = 0;
22082 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22083
22084 if (vctxt->nbAttrInfos != 0)
22085 xmlSchemaClearAttrInfos(vctxt);
22086 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22087 /*
22088 * This element was not expected;
22089 * we will not validate child elements of broken parents.
22090 * Skip validation of all content of the parent.
22091 */
22092 vctxt->skipDepth = vctxt->depth -1;
22093 goto end_elem;
22094 }
22095 if ((inode->typeDef == NULL) ||
22096 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22097 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022098 * 1. the type definition might be missing if the element was
22099 * error prone
22100 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022101 */
22102 goto end_elem;
22103 }
22104 /*
22105 * Check the content model.
22106 */
22107 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22108 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22109
22110 /*
22111 * Workaround for "anyType".
22112 */
22113 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22114 goto character_content;
22115
22116 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22117 xmlChar *values[10];
22118 int terminal, nbval = 10, nbneg;
22119
22120 if (inode->regexCtxt == NULL) {
22121 /*
22122 * Create the regex context.
22123 */
22124 inode->regexCtxt =
22125 xmlRegNewExecCtxt(inode->typeDef->contModel,
22126 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22127 vctxt);
22128 if (inode->regexCtxt == NULL) {
22129 VERROR_INT("xmlSchemaValidatorPopElem",
22130 "failed to create a regex context");
22131 goto internal_error;
22132 }
22133#ifdef DEBUG_AUTOMATA
22134 xmlGenericError(xmlGenericErrorContext,
22135 "AUTOMATON create on '%s'\n", inode->localName);
22136#endif
22137 }
22138 /*
22139 * Get hold of the still expected content, since a further
22140 * call to xmlRegExecPushString() will loose this information.
22141 */
22142 xmlRegExecNextValues(inode->regexCtxt,
22143 &nbval, &nbneg, &values[0], &terminal);
22144 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22145 if (ret <= 0) {
22146 /*
22147 * Still missing something.
22148 */
22149 ret = 1;
22150 inode->flags |=
22151 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22152 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22153 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22154 "Missing child element(s)",
22155 nbval, nbneg, values);
22156#ifdef DEBUG_AUTOMATA
22157 xmlGenericError(xmlGenericErrorContext,
22158 "AUTOMATON missing ERROR on '%s'\n",
22159 inode->localName);
22160#endif
22161 } else {
22162 /*
22163 * Content model is satisfied.
22164 */
22165 ret = 0;
22166#ifdef DEBUG_AUTOMATA
22167 xmlGenericError(xmlGenericErrorContext,
22168 "AUTOMATON succeeded on '%s'\n",
22169 inode->localName);
22170#endif
22171 }
22172
22173 }
22174 }
22175 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22176 goto end_elem;
22177
22178character_content:
22179
22180 if (vctxt->value != NULL) {
22181 xmlSchemaFreeValue(vctxt->value);
22182 vctxt->value = NULL;
22183 }
22184 /*
22185 * Check character content.
22186 */
22187 if (inode->decl == NULL) {
22188 /*
22189 * Speedup if no declaration exists.
22190 */
22191 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22192 ret = xmlSchemaVCheckINodeDataType(vctxt,
22193 inode, inode->typeDef, inode->value);
22194 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22195 ret = xmlSchemaVCheckINodeDataType(vctxt,
22196 inode, inode->typeDef->contentTypeDef,
22197 inode->value);
22198 }
22199 if (ret < 0) {
22200 VERROR_INT("xmlSchemaValidatorPopElem",
22201 "calling xmlSchemaVCheckCVCSimpleType()");
22202 goto internal_error;
22203 }
22204 goto end_elem;
22205 }
22206 /*
22207 * cvc-elt (3.3.4) : 5
22208 * The appropriate case among the following must be true:
22209 */
22210 /*
22211 * cvc-elt (3.3.4) : 5.1
22212 * If the declaration has a {value constraint},
22213 * the item has neither element nor character [children] and
22214 * clause 3.2 has not applied, then all of the following must be true:
22215 */
22216 if ((inode->decl->value != NULL) &&
22217 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22218 (! INODE_NILLED(inode))) {
22219 /*
22220 * cvc-elt (3.3.4) : 5.1.1
22221 * If the ·actual type definition· is a ·local type definition·
22222 * then the canonical lexical representation of the {value constraint}
22223 * value must be a valid default for the ·actual type definition· as
22224 * defined in Element Default Valid (Immediate) (§3.3.6).
22225 */
22226 /*
22227 * NOTE: 'local' above means types aquired by xsi:type.
22228 * NOTE: Although the *canonical* value is stated, it is not
22229 * relevant if canonical or not. Additionally XML Schema 1.1
22230 * will removed this requirement as well.
22231 */
22232 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22233
22234 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22235 inode->decl->value, &(inode->val));
22236 if (ret != 0) {
22237 if (ret < 0) {
22238 VERROR_INT("xmlSchemaValidatorPopElem",
22239 "calling xmlSchemaCheckCOSValidDefault()");
22240 goto internal_error;
22241 }
22242 goto end_elem;
22243 }
22244 /*
22245 * Stop here, to avoid redundant validation of the value
22246 * (see following).
22247 */
22248 goto default_psvi;
22249 }
22250 /*
22251 * cvc-elt (3.3.4) : 5.1.2
22252 * The element information item with the canonical lexical
22253 * representation of the {value constraint} value used as its
22254 * ·normalized value· must be ·valid· with respect to the
22255 * ·actual type definition· as defined by Element Locally Valid (Type)
22256 * (§3.3.4).
22257 */
22258 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22259 ret = xmlSchemaVCheckINodeDataType(vctxt,
22260 inode, inode->typeDef, inode->decl->value);
22261 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22262 ret = xmlSchemaVCheckINodeDataType(vctxt,
22263 inode, inode->typeDef->contentTypeDef,
22264 inode->decl->value);
22265 }
22266 if (ret != 0) {
22267 if (ret < 0) {
22268 VERROR_INT("xmlSchemaValidatorPopElem",
22269 "calling xmlSchemaVCheckCVCSimpleType()");
22270 goto internal_error;
22271 }
22272 goto end_elem;
22273 }
22274
22275default_psvi:
22276 /*
22277 * PSVI: Create a text node on the instance element.
22278 */
22279 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22280 (inode->node != NULL)) {
22281 xmlNodePtr textChild;
22282 xmlChar *normValue;
22283 /*
22284 * VAL TODO: Normalize the value.
22285 */
22286 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22287 inode->decl->value);
22288 if (normValue != NULL) {
22289 textChild = xmlNewText(BAD_CAST normValue);
22290 xmlFree(normValue);
22291 } else
22292 textChild = xmlNewText(inode->decl->value);
22293 if (textChild == NULL) {
22294 VERROR_INT("xmlSchemaValidatorPopElem",
22295 "calling xmlNewText()");
22296 goto internal_error;
22297 } else
22298 xmlAddChild(inode->node, textChild);
22299 }
22300
22301 } else if (! INODE_NILLED(inode)) {
22302 /*
22303 * 5.2.1 The element information item must be ·valid· with respect
22304 * to the ·actual type definition· as defined by Element Locally
22305 * Valid (Type) (§3.3.4).
22306 */
22307 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22308 /*
22309 * SPEC (cvc-type) (3.1)
22310 * "If the type definition is a simple type definition, ..."
22311 * (3.1.3) "If clause 3.2 of Element Locally Valid
22312 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22313 * must be ·valid· with respect to the type definition as defined
22314 * by String Valid (§3.14.4).
22315 */
22316 ret = xmlSchemaVCheckINodeDataType(vctxt,
22317 inode, inode->typeDef, inode->value);
22318 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22319 /*
22320 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22321 * definition, then the element information item must be
22322 * ·valid· with respect to the type definition as per
22323 * Element Locally Valid (Complex Type) (§3.4.4);"
22324 *
22325 * SPEC (cvc-complex-type) (2.2)
22326 * "If the {content type} is a simple type definition, ...
22327 * the ·normalized value· of the element information item is
22328 * ·valid· with respect to that simple type definition as
22329 * defined by String Valid (§3.14.4)."
22330 */
22331 ret = xmlSchemaVCheckINodeDataType(vctxt,
22332 inode, inode->typeDef->contentTypeDef, inode->value);
22333 }
22334 if (ret != 0) {
22335 if (ret < 0) {
22336 VERROR_INT("xmlSchemaValidatorPopElem",
22337 "calling xmlSchemaVCheckCVCSimpleType()");
22338 goto internal_error;
22339 }
22340 goto end_elem;
22341 }
22342 /*
22343 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22344 * not applied, all of the following must be true:
22345 */
22346 if ((inode->decl->value != NULL) &&
22347 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22348
22349 /*
22350 * TODO: We will need a computed value, when comparison is
22351 * done on computed values.
22352 */
22353 /*
22354 * 5.2.2.1 The element information item must have no element
22355 * information item [children].
22356 */
22357 if (inode->flags &
22358 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22359 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22360 VERROR(ret, NULL,
22361 "The content must not containt element nodes since "
22362 "there is a fixed value constraint");
22363 goto end_elem;
22364 } else {
22365 /*
22366 * 5.2.2.2 The appropriate case among the following must
22367 * be true:
22368 */
22369 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22370 /*
22371 * 5.2.2.2.1 If the {content type} of the ·actual type
22372 * definition· is mixed, then the *initial value* of the
22373 * item must match the canonical lexical representation
22374 * of the {value constraint} value.
22375 *
22376 * ... the *initial value* of an element information
22377 * item is the string composed of, in order, the
22378 * [character code] of each character information item in
22379 * the [children] of that element information item.
22380 */
22381 if (! xmlStrEqual(inode->value, inode->decl->value)){
22382 /*
22383 * VAL TODO: Report invalid & expected values as well.
22384 * VAL TODO: Implement the canonical stuff.
22385 */
22386 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22387 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22388 ret, NULL, NULL,
22389 "The initial value '%s' does not match the fixed "
22390 "value constraint '%s'",
22391 inode->value, inode->decl->value);
22392 goto end_elem;
22393 }
22394 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22395 /*
22396 * 5.2.2.2.2 If the {content type} of the ·actual type
22397 * definition· is a simple type definition, then the
22398 * *actual value* of the item must match the canonical
22399 * lexical representation of the {value constraint} value.
22400 */
22401 /*
22402 * VAL TODO: *actual value* is the normalized value, impl.
22403 * this.
22404 * VAL TODO: Report invalid & expected values as well.
22405 * VAL TODO: Implement a comparison with the computed values.
22406 */
22407 if (! xmlStrEqual(inode->value,
22408 inode->decl->value)) {
22409 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22410 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22411 ret, NULL, NULL,
22412 "The actual value '%s' does not match the fixed "
22413 "value constraint '%s'",
22414 inode->value,
22415 inode->decl->value);
22416 goto end_elem;
22417 }
22418 }
22419 }
22420 }
22421 }
22422
22423end_elem:
22424 if (vctxt->depth < 0) {
22425 /* TODO: raise error? */
22426 return (0);
22427 }
22428 if (vctxt->depth == vctxt->skipDepth)
22429 vctxt->skipDepth = -1;
22430 /*
22431 * Evaluate the history of XPath state objects.
22432 */
22433 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22434 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022435 /*
22436 * TODO: 6 The element information item must be ·valid· with respect to each of
22437 * the {identity-constraint definitions} as per Identity-constraint
22438 * Satisfied (§3.11.4).
22439 */
22440 /*
22441 * Validate IDC keyrefs.
22442 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022443 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22444 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022445 /*
22446 * Merge/free the IDC table.
22447 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022448 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022449#ifdef DEBUG_IDC
22450 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022451 inode->nsName,
22452 inode->localName,
22453 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022454#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022455 if (vctxt->depth > 0) {
22456 /*
22457 * Merge the IDC node table with the table of the parent node.
22458 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022459 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22460 goto internal_error;
22461 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022462 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022463 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022464 * Clear the current ielem.
22465 * VAL TODO: Don't free the PSVI IDC tables if they are
22466 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022467 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022468 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022469 /*
22470 * Skip further processing if we are on the validation root.
22471 */
22472 if (vctxt->depth == 0) {
22473 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022474 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022475 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022476 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022477 /*
22478 * Reset the bubbleDepth if needed.
22479 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022480 if (vctxt->aidcs != NULL) {
22481 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22482 do {
22483 if (aidc->bubbleDepth == vctxt->depth) {
22484 /*
22485 * A bubbleDepth of a key/unique IDC matches the current
22486 * depth, this means that we are leaving the scope of the
22487 * top-most keyref IDC.
22488 */
22489 aidc->bubbleDepth = -1;
22490 }
22491 aidc = aidc->next;
22492 } while (aidc != NULL);
22493 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022494 vctxt->depth--;
22495 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022496 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022497 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022498 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22499 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022500 return (ret);
22501
22502internal_error:
22503 vctxt->err = -1;
22504 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022505}
22506
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022507/*
22508* 3.4.4 Complex Type Definition Validation Rules
22509* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22510*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022511static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022512xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022513{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022514 xmlSchemaNodeInfoPtr pielem;
22515 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022516 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022517
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022518 if (vctxt->depth <= 0) {
22519 VERROR_INT("xmlSchemaValidateChildElem",
22520 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022521 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022522 }
22523 pielem = vctxt->elemInfos[vctxt->depth -1];
22524 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22525 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022526 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022527 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022528 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022529 if (INODE_NILLED(pielem)) {
22530 /*
22531 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22532 */
22533 ACTIVATE_PARENT_ELEM;
22534 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22535 VERROR(ret, NULL,
22536 "Neither character nor element content is allowed, "
22537 "because the element was 'nilled'");
22538 ACTIVATE_ELEM;
22539 goto unexpected_elem;
22540 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022541
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022542 ptype = pielem->typeDef;
22543
22544 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22545 /*
22546 * Workaround for "anyType": we have currently no content model
22547 * assigned for "anyType", so handle it explicitely.
22548 * "anyType" has an unbounded, lax "any" wildcard.
22549 */
22550 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22551 vctxt->inode->localName,
22552 vctxt->inode->nsName);
22553
22554 if (vctxt->inode->decl == NULL) {
22555 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022556 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022557 * Process "xsi:type".
22558 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022559 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022560 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22561 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22562 if (iattr != NULL) {
22563 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22564 &(vctxt->inode->typeDef), NULL);
22565 if (ret != 0) {
22566 if (ret == -1) {
22567 VERROR_INT("xmlSchemaValidateChildElem",
22568 "calling xmlSchemaProcessXSIType() to "
22569 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022570 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022571 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022572 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022573 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022574 } else {
22575 /*
22576 * Fallback to "anyType".
22577 *
22578 * SPEC (cvc-assess-elt)
22579 * "If the item cannot be ·strictly assessed·, [...]
22580 * an element information item's schema validity may be laxly
22581 * assessed if its ·context-determined declaration· is not
22582 * skip by ·validating· with respect to the ·ur-type
22583 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22584 */
22585 vctxt->inode->typeDef =
22586 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022587 }
22588 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022589 return (0);
22590 }
22591
22592 switch (ptype->contentType) {
22593 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022594 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022595 * SPEC (2.1) "If the {content type} is empty, then the
22596 * element information item has no character or element
22597 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022598 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022599 ACTIVATE_PARENT_ELEM
22600 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22601 VERROR(ret, NULL,
22602 "Element content is not allowed, "
22603 "because the content type is empty");
22604 ACTIVATE_ELEM
22605 goto unexpected_elem;
22606 break;
22607
22608 case XML_SCHEMA_CONTENT_MIXED:
22609 case XML_SCHEMA_CONTENT_ELEMENTS: {
22610 xmlRegExecCtxtPtr regexCtxt;
22611 xmlChar *values[10];
22612 int terminal, nbval = 10, nbneg;
22613
22614 /* VAL TODO: Optimized "anyType" validation.*/
22615
22616 if (ptype->contModel == NULL) {
22617 VERROR_INT("xmlSchemaValidateChildElem",
22618 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022619 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022620 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022621 /*
22622 * Safety belf for evaluation if the cont. model was already
22623 * examined to be invalid.
22624 */
22625 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22626 VERROR_INT("xmlSchemaValidateChildElem",
22627 "validating elem, but elem content is already invalid");
22628 return (-1);
22629 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022631 regexCtxt = pielem->regexCtxt;
22632 if (regexCtxt == NULL) {
22633 /*
22634 * Create the regex context.
22635 */
22636 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22637 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22638 vctxt);
22639 if (regexCtxt == NULL) {
22640 VERROR_INT("xmlSchemaValidateChildElem",
22641 "failed to create a regex context");
22642 return (-1);
22643 }
22644 pielem->regexCtxt = regexCtxt;
22645#ifdef DEBUG_AUTOMATA
22646 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22647 pielem->localName);
22648#endif
22649 }
22650
22651 /*
22652 * SPEC (2.4) "If the {content type} is element-only or mixed,
22653 * then the sequence of the element information item's
22654 * element information item [children], if any, taken in
22655 * order, is ·valid· with respect to the {content type}'s
22656 * particle, as defined in Element Sequence Locally Valid
22657 * (Particle) (§3.9.4)."
22658 */
22659 ret = xmlRegExecPushString2(regexCtxt,
22660 vctxt->inode->localName,
22661 vctxt->inode->nsName,
22662 vctxt->inode);
22663#ifdef DEBUG_AUTOMATA
22664 if (ret < 0)
22665 xmlGenericError(xmlGenericErrorContext,
22666 "AUTOMATON push ERROR for '%s' on '%s'\n",
22667 vctxt->inode->localName, pielem->localName);
22668 else
22669 xmlGenericError(xmlGenericErrorContext,
22670 "AUTOMATON push OK for '%s' on '%s'\n",
22671 vctxt->inode->localName, pielem->localName);
22672#endif
22673 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22674 VERROR_INT("xmlSchemaValidateChildElem",
22675 "calling xmlRegExecPushString2()");
22676 return (-1);
22677 }
22678 if (ret < 0) {
22679 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22680 &values[0], &terminal);
22681 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22682 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22683 "This element is not expected",
22684 nbval, nbneg, values);
22685 ret = vctxt->err;
22686 goto unexpected_elem;
22687 } else
22688 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022689 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022690 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022691 case XML_SCHEMA_CONTENT_SIMPLE:
22692 case XML_SCHEMA_CONTENT_BASIC:
22693 ACTIVATE_PARENT_ELEM
22694 if (IS_COMPLEX_TYPE(ptype)) {
22695 /*
22696 * SPEC (cvc-complex-type) (2.2)
22697 * "If the {content type} is a simple type definition, then
22698 * the element information item has no element information
22699 * item [children], ..."
22700 */
22701 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22702 VERROR(ret, NULL, "Element content is not allowed, "
22703 "because the content type is a simple type definition");
22704 } else {
22705 /*
22706 * SPEC (cvc-type) (3.1.2) "The element information item must
22707 * have no element information item [children]."
22708 */
22709 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22710 VERROR(ret, NULL, "Element content is not allowed, "
22711 "because the type definition is simple");
22712 }
22713 ACTIVATE_ELEM
22714 ret = vctxt->err;
22715 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022716 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022717
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022718 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022719 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022720 }
22721 return (ret);
22722unexpected_elem:
22723 /*
22724 * Pop this element and set the skipDepth to skip
22725 * all further content of the parent element.
22726 */
22727 vctxt->skipDepth = vctxt->depth;
22728 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22729 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22730 return (ret);
22731}
22732
22733#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22734#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22735#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22736
22737static int
22738xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22739 int nodeType, const xmlChar *value, int len,
22740 int mode, int *consumed)
22741{
22742 /*
22743 * Unfortunately we have to duplicate the text sometimes.
22744 * OPTIMIZE: Maybe we could skip it, if:
22745 * 1. content type is simple
22746 * 2. whitespace is "collapse"
22747 * 3. it consists of whitespace only
22748 *
22749 * Process character content.
22750 */
22751 if (consumed != NULL)
22752 *consumed = 0;
22753 if (INODE_NILLED(vctxt->inode)) {
22754 /*
22755 * SPEC cvc-elt (3.3.4 - 3.2.1)
22756 * "The element information item must have no character or
22757 * element information item [children]."
22758 */
22759 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22760 "Neither character nor element content is allowed "
22761 "because the element is 'nilled'");
22762 return (vctxt->err);
22763 }
22764 /*
22765 * SPEC (2.1) "If the {content type} is empty, then the
22766 * element information item has no character or element
22767 * information item [children]."
22768 */
22769 if (vctxt->inode->typeDef->contentType ==
22770 XML_SCHEMA_CONTENT_EMPTY) {
22771 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22772 "Character content is not allowed, "
22773 "because the content type is empty");
22774 return (vctxt->err);
22775 }
22776
22777 if (vctxt->inode->typeDef->contentType ==
22778 XML_SCHEMA_CONTENT_ELEMENTS) {
22779 if ((nodeType != XML_TEXT_NODE) ||
22780 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22781 /*
22782 * SPEC cvc-complex-type (2.3)
22783 * "If the {content type} is element-only, then the
22784 * element information item has no character information
22785 * item [children] other than those whose [character
22786 * code] is defined as a white space in [XML 1.0 (Second
22787 * Edition)]."
22788 */
22789 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22790 "Character content other than whitespace is not allowed "
22791 "because the content type is 'element-only'");
22792 return (vctxt->err);
22793 }
22794 return (0);
22795 }
22796
22797 if ((value == NULL) || (value[0] == 0))
22798 return (0);
22799 /*
22800 * Save the value.
22801 * NOTE that even if the content type is *mixed*, we need the
22802 * *initial value* for default/fixed value constraints.
22803 */
22804 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22805 ((vctxt->inode->decl == NULL) ||
22806 (vctxt->inode->decl->value == NULL)))
22807 return (0);
22808
22809 if (vctxt->inode->value == NULL) {
22810 /*
22811 * Set the value.
22812 */
22813 switch (mode) {
22814 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22815 /*
22816 * When working on a tree.
22817 */
22818 vctxt->inode->value = value;
22819 break;
22820 case XML_SCHEMA_PUSH_TEXT_CREATED:
22821 /*
22822 * When working with the reader.
22823 * The value will be freed by the element info.
22824 */
22825 vctxt->inode->value = value;
22826 if (consumed != NULL)
22827 *consumed = 1;
22828 vctxt->inode->flags |=
22829 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22830 break;
22831 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22832 /*
22833 * When working with SAX.
22834 * The value will be freed by the element info.
22835 */
22836 if (len != -1)
22837 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22838 else
22839 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22840 vctxt->inode->flags |=
22841 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22842 break;
22843 default:
22844 break;
22845 }
22846 } else {
22847 /*
22848 * Concat the value.
22849 */
22850 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022851 vctxt->inode->value = BAD_CAST xmlStrncat(
22852 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022853 } else {
22854 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022855 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022856 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22857 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022858 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022859
22860 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022861}
22862
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022863static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022864xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022865{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022866 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022867
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022868 if ((vctxt->skipDepth != -1) &&
22869 (vctxt->depth >= vctxt->skipDepth)) {
22870 VERROR_INT("xmlSchemaValidateElem",
22871 "in skip-state");
22872 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022873 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022874 if (vctxt->xsiAssemble) {
22875 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22876 goto internal_error;
22877 }
22878 if (vctxt->depth > 0) {
22879 /*
22880 * Validate this element against the content model
22881 * of the parent.
22882 */
22883 ret = xmlSchemaValidateChildElem(vctxt);
22884 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022885 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022886 VERROR_INT("xmlSchemaValidateElem",
22887 "calling xmlSchemaStreamValidateChildElement()");
22888 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022889 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022890 goto exit;
22891 }
22892 if (vctxt->depth == vctxt->skipDepth)
22893 goto exit;
22894 if ((vctxt->inode->decl == NULL) &&
22895 (vctxt->inode->typeDef == NULL)) {
22896 VERROR_INT("xmlSchemaValidateElem",
22897 "the child element was valid but neither the "
22898 "declaration nor the type was set");
22899 goto internal_error;
22900 }
22901 } else {
22902 /*
22903 * Get the declaration of the validation root.
22904 */
22905 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22906 vctxt->inode->localName,
22907 vctxt->inode->nsName);
22908 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022909 ret = XML_SCHEMAV_CVC_ELT_1;
22910 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022911 "No matching global declaration available "
22912 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022913 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022914 }
22915 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022916
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022917 if (vctxt->inode->decl == NULL)
22918 goto type_validation;
22919
22920 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22921 int skip;
22922 /*
22923 * Wildcards.
22924 */
22925 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22926 if (ret != 0) {
22927 if (ret < 0) {
22928 VERROR_INT("xmlSchemaValidateElem",
22929 "calling xmlSchemaValidateElemWildcard()");
22930 goto internal_error;
22931 }
22932 goto exit;
22933 }
22934 if (skip) {
22935 vctxt->skipDepth = vctxt->depth;
22936 goto exit;
22937 }
22938 /*
22939 * The declaration might be set by the wildcard validation,
22940 * when the processContents is "lax" or "strict".
22941 */
22942 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22943 /*
22944 * Clear the "decl" field to not confuse further processing.
22945 */
22946 vctxt->inode->decl = NULL;
22947 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022948 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022949 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022950 /*
22951 * Validate against the declaration.
22952 */
22953 ret = xmlSchemaValidateElemDecl(vctxt);
22954 if (ret != 0) {
22955 if (ret < 0) {
22956 VERROR_INT("xmlSchemaValidateElem",
22957 "calling xmlSchemaValidateElemDecl()");
22958 goto internal_error;
22959 }
22960 goto exit;
22961 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022962 /*
22963 * Validate against the type definition.
22964 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022965type_validation:
22966
22967 if (vctxt->inode->typeDef == NULL) {
22968 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22969 ret = XML_SCHEMAV_CVC_TYPE_1;
22970 VERROR(ret, NULL,
22971 "The type definition is absent");
22972 goto exit;
22973 }
22974 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
22975 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
22976 ret = XML_SCHEMAV_CVC_TYPE_2;
22977 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022978 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022979 goto exit;
22980 }
22981 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022982 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022983 * during validation against the declaration. This must be done
22984 * _before_ attribute validation.
22985 */
22986 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
22987 if (ret == -1) {
22988 VERROR_INT("xmlSchemaValidateElem",
22989 "calling xmlSchemaXPathEvaluate()");
22990 goto internal_error;
22991 }
22992 /*
22993 * Validate attributes.
22994 */
22995 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
22996 if ((vctxt->nbAttrInfos != 0) ||
22997 (vctxt->inode->typeDef->attributeUses != NULL)) {
22998
22999 ret = xmlSchemaVAttributesComplex(vctxt);
23000 }
23001 } else if (vctxt->nbAttrInfos != 0) {
23002
23003 ret = xmlSchemaVAttributesSimple(vctxt);
23004 }
23005 /*
23006 * Clear registered attributes.
23007 */
23008 if (vctxt->nbAttrInfos != 0)
23009 xmlSchemaClearAttrInfos(vctxt);
23010 if (ret == -1) {
23011 VERROR_INT("xmlSchemaValidateElem",
23012 "calling attributes validation");
23013 goto internal_error;
23014 }
23015 /*
23016 * Don't return an error if attributes are invalid on purpose.
23017 */
23018 ret = 0;
23019
23020exit:
23021 if (ret != 0)
23022 vctxt->skipDepth = vctxt->depth;
23023 return (ret);
23024internal_error:
23025 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023026}
23027
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023028#ifdef XML_SCHEMA_READER_ENABLED
23029static int
23030xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023031{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023032 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
23033 int depth, nodeType, ret = 0, consumed;
23034 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023035
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023036 vctxt->depth = -1;
23037 ret = xmlTextReaderRead(vctxt->reader);
23038 /*
23039 * Move to the document element.
23040 */
23041 while (ret == 1) {
23042 nodeType = xmlTextReaderNodeType(vctxt->reader);
23043 if (nodeType == XML_ELEMENT_NODE)
23044 goto root_found;
23045 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023046 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023047 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023048
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023049root_found:
23050
23051 do {
23052 depth = xmlTextReaderDepth(vctxt->reader);
23053 nodeType = xmlTextReaderNodeType(vctxt->reader);
23054
23055 if (nodeType == XML_ELEMENT_NODE) {
23056
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023057 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023058 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23059 VERROR_INT("xmlSchemaVReaderWalk",
23060 "calling xmlSchemaValidatorPushElem()");
23061 goto internal_error;
23062 }
23063 ielem = vctxt->inode;
23064 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23065 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23066 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23067 /*
23068 * Is the element empty?
23069 */
23070 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23071 if (ret == -1) {
23072 VERROR_INT("xmlSchemaVReaderWalk",
23073 "calling xmlTextReaderIsEmptyElement()");
23074 goto internal_error;
23075 }
23076 if (ret) {
23077 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23078 }
23079 /*
23080 * Register attributes.
23081 */
23082 vctxt->nbAttrInfos = 0;
23083 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23084 if (ret == -1) {
23085 VERROR_INT("xmlSchemaVReaderWalk",
23086 "calling xmlTextReaderMoveToFirstAttribute()");
23087 goto internal_error;
23088 }
23089 if (ret == 1) {
23090 do {
23091 /*
23092 * VAL TODO: How do we know that the reader works on a
23093 * node tree, to be able to pass a node here?
23094 */
23095 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23096 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23097 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23098 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23099
23100 VERROR_INT("xmlSchemaVReaderWalk",
23101 "calling xmlSchemaValidatorPushAttribute()");
23102 goto internal_error;
23103 }
23104 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23105 if (ret == -1) {
23106 VERROR_INT("xmlSchemaVReaderWalk",
23107 "calling xmlTextReaderMoveToFirstAttribute()");
23108 goto internal_error;
23109 }
23110 } while (ret == 1);
23111 /*
23112 * Back to element position.
23113 */
23114 ret = xmlTextReaderMoveToElement(vctxt->reader);
23115 if (ret == -1) {
23116 VERROR_INT("xmlSchemaVReaderWalk",
23117 "calling xmlTextReaderMoveToElement()");
23118 goto internal_error;
23119 }
23120 }
23121 /*
23122 * Validate the element.
23123 */
23124 ret= xmlSchemaValidateElem(vctxt);
23125 if (ret != 0) {
23126 if (ret == -1) {
23127 VERROR_INT("xmlSchemaVReaderWalk",
23128 "calling xmlSchemaValidateElem()");
23129 goto internal_error;
23130 }
23131 goto exit;
23132 }
23133 if (vctxt->depth == vctxt->skipDepth) {
23134 int curDepth;
23135 /*
23136 * Skip all content.
23137 */
23138 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23139 ret = xmlTextReaderRead(vctxt->reader);
23140 curDepth = xmlTextReaderDepth(vctxt->reader);
23141 while ((ret == 1) && (curDepth != depth)) {
23142 ret = xmlTextReaderRead(vctxt->reader);
23143 curDepth = xmlTextReaderDepth(vctxt->reader);
23144 }
23145 if (ret < 0) {
23146 /*
23147 * VAL TODO: A reader error occured; what to do here?
23148 */
23149 ret = 1;
23150 goto exit;
23151 }
23152 }
23153 goto leave_elem;
23154 }
23155 /*
23156 * READER VAL TODO: Is an END_ELEM really never called
23157 * if the elem is empty?
23158 */
23159 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23160 goto leave_elem;
23161 } else if (nodeType == END_ELEM) {
23162 /*
23163 * Process END of element.
23164 */
23165leave_elem:
23166 ret = xmlSchemaValidatorPopElem(vctxt);
23167 if (ret != 0) {
23168 if (ret < 0) {
23169 VERROR_INT("xmlSchemaVReaderWalk",
23170 "calling xmlSchemaValidatorPopElem()");
23171 goto internal_error;
23172 }
23173 goto exit;
23174 }
23175 if (vctxt->depth >= 0)
23176 ielem = vctxt->inode;
23177 else
23178 ielem = NULL;
23179 } else if ((nodeType == XML_TEXT_NODE) ||
23180 (nodeType == XML_CDATA_SECTION_NODE) ||
23181 (nodeType == WHTSP) ||
23182 (nodeType == SIGN_WHTSP)) {
23183 /*
23184 * Process character content.
23185 */
23186 xmlChar *value;
23187
23188 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23189 nodeType = XML_TEXT_NODE;
23190
23191 value = xmlTextReaderValue(vctxt->reader);
23192 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23193 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23194 if (! consumed)
23195 xmlFree(value);
23196 if (ret == -1) {
23197 VERROR_INT("xmlSchemaVReaderWalk",
23198 "calling xmlSchemaVPushText()");
23199 goto internal_error;
23200 }
23201 } else if ((nodeType == XML_ENTITY_NODE) ||
23202 (nodeType == XML_ENTITY_REF_NODE)) {
23203 /*
23204 * VAL TODO: What to do with entities?
23205 */
23206 TODO
23207 }
23208 /*
23209 * Read next node.
23210 */
23211 ret = xmlTextReaderRead(vctxt->reader);
23212 } while (ret == 1);
23213
23214exit:
23215 return (ret);
23216internal_error:
23217 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023218}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023219#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023220
23221/************************************************************************
23222 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023223 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023224 * *
23225 ************************************************************************/
23226
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023227#ifdef XML_SCHEMA_SAX_ENABLED
23228/*
23229* Process text content.
23230*/
23231static void
23232xmlSchemaSAXHandleText(void *ctx,
23233 const xmlChar * ch,
23234 int len)
23235{
23236 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23237
23238 if (vctxt->depth < 0)
23239 return;
23240 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23241 return;
23242 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23243 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23244 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23245 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23246 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23247 "calling xmlSchemaVPushText()");
23248 vctxt->err = -1;
23249 xmlStopParser(vctxt->parserCtxt);
23250 }
23251}
23252
23253/*
23254* Process CDATA content.
23255*/
23256static void
23257xmlSchemaSAXHandleCDataSection(void *ctx,
23258 const xmlChar * ch,
23259 int len)
23260{
23261 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23262
23263 if (vctxt->depth < 0)
23264 return;
23265 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23266 return;
23267 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23268 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23269 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23270 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23271 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23272 "calling xmlSchemaVPushText()");
23273 vctxt->err = -1;
23274 xmlStopParser(vctxt->parserCtxt);
23275 }
23276}
23277
23278static void
23279xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23280 const xmlChar * name ATTRIBUTE_UNUSED)
23281{
23282 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23283
23284 if (vctxt->depth < 0)
23285 return;
23286 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23287 return;
23288 /* SAX VAL TODO: What to do here? */
23289 TODO
23290}
23291
23292static void
23293xmlSchemaSAXHandleStartElementNs(void *ctx,
23294 const xmlChar * localname,
23295 const xmlChar * prefix ATTRIBUTE_UNUSED,
23296 const xmlChar * URI,
23297 int nb_namespaces,
23298 const xmlChar ** namespaces,
23299 int nb_attributes,
23300 int nb_defaulted ATTRIBUTE_UNUSED,
23301 const xmlChar ** attributes)
23302{
23303 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23304 int ret;
23305 xmlSchemaNodeInfoPtr ielem;
23306 int i, j;
23307
23308 /*
23309 * SAX VAL TODO: What to do with nb_defaulted?
23310 */
23311 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023312 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023313 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023314 vctxt->depth++;
23315 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023316 return;
23317 /*
23318 * Push the element.
23319 */
23320 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23321 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23322 "calling xmlSchemaValidatorPushElem()");
23323 goto internal_error;
23324 }
23325 ielem = vctxt->inode;
23326 ielem->localName = localname;
23327 ielem->nsName = URI;
23328 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23329 /*
23330 * Register namespaces on the elem info.
23331 */
23332 if (nb_namespaces != 0) {
23333 /*
23334 * Although the parser builds its own namespace list,
23335 * we have no access to it, so we'll use an own one.
23336 */
23337 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23338 /*
23339 * Store prefix and namespace name.
23340 */
23341 if (ielem->nsBindings == NULL) {
23342 ielem->nsBindings =
23343 (const xmlChar **) xmlMalloc(10 *
23344 sizeof(const xmlChar *));
23345 if (ielem->nsBindings == NULL) {
23346 xmlSchemaVErrMemory(vctxt,
23347 "allocating namespace bindings for SAX validation",
23348 NULL);
23349 goto internal_error;
23350 }
23351 ielem->nbNsBindings = 0;
23352 ielem->sizeNsBindings = 5;
23353 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23354 ielem->sizeNsBindings *= 2;
23355 ielem->nsBindings =
23356 (const xmlChar **) xmlRealloc(
23357 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023358 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023359 if (ielem->nsBindings == NULL) {
23360 xmlSchemaVErrMemory(vctxt,
23361 "re-allocating namespace bindings for SAX validation",
23362 NULL);
23363 goto internal_error;
23364 }
23365 }
23366
23367 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23368 if (namespaces[j+1][0] == 0) {
23369 /*
23370 * Handle xmlns="".
23371 */
23372 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23373 } else
23374 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23375 namespaces[j+1];
23376 ielem->nbNsBindings++;
23377 }
23378 }
23379 /*
23380 * Register attributes.
23381 * SAX VAL TODO: We are not adding namespace declaration
23382 * attributes yet.
23383 */
23384 if (nb_attributes != 0) {
23385 xmlChar *value;
23386
23387 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23388 /*
23389 * Duplicate the value.
23390 */
23391 value = xmlStrndup(attributes[j+3],
23392 attributes[j+4] - attributes[j+3]);
23393 ret = xmlSchemaValidatorPushAttribute(vctxt,
23394 NULL, attributes[j], attributes[j+2], 0,
23395 value, 1);
23396 if (ret == -1) {
23397 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23398 "calling xmlSchemaValidatorPushAttribute()");
23399 goto internal_error;
23400 }
23401 }
23402 }
23403 /*
23404 * Validate the element.
23405 */
23406 ret = xmlSchemaValidateElem(vctxt);
23407 if (ret != 0) {
23408 if (ret == -1) {
23409 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23410 "calling xmlSchemaValidateElem()");
23411 goto internal_error;
23412 }
23413 goto exit;
23414 }
23415
23416exit:
23417 return;
23418internal_error:
23419 vctxt->err = -1;
23420 xmlStopParser(vctxt->parserCtxt);
23421 return;
23422}
23423
23424static void
23425xmlSchemaSAXHandleEndElementNs(void *ctx,
23426 const xmlChar * localname ATTRIBUTE_UNUSED,
23427 const xmlChar * prefix ATTRIBUTE_UNUSED,
23428 const xmlChar * URI ATTRIBUTE_UNUSED)
23429{
23430 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23431 int res;
23432
23433 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023434 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023435 */
23436 if (vctxt->skipDepth != -1) {
23437 if (vctxt->depth > vctxt->skipDepth) {
23438 vctxt->depth--;
23439 return;
23440 } else
23441 vctxt->skipDepth = -1;
23442 }
23443 /*
23444 * SAX VAL TODO: Just a temporary check.
23445 */
23446 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23447 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23448 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23449 "elem pop mismatch");
23450 }
23451 res = xmlSchemaValidatorPopElem(vctxt);
23452 if (res != 0) {
23453 if (res < 0) {
23454 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23455 "calling xmlSchemaValidatorPopElem()");
23456 goto internal_error;
23457 }
23458 goto exit;
23459 }
23460exit:
23461 return;
23462internal_error:
23463 vctxt->err = -1;
23464 xmlStopParser(vctxt->parserCtxt);
23465 return;
23466}
23467#endif
23468
Daniel Veillard4255d502002-04-16 15:50:10 +000023469/************************************************************************
23470 * *
23471 * Validation interfaces *
23472 * *
23473 ************************************************************************/
23474
23475/**
23476 * xmlSchemaNewValidCtxt:
23477 * @schema: a precompiled XML Schemas
23478 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023479 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023480 *
23481 * Returns the validation context or NULL in case of error
23482 */
23483xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023484xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23485{
Daniel Veillard4255d502002-04-16 15:50:10 +000023486 xmlSchemaValidCtxtPtr ret;
23487
23488 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23489 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023490 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023491 return (NULL);
23492 }
23493 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023494 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23495 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023496 return (ret);
23497}
23498
23499/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023500 * xmlSchemaClearValidCtxt:
23501 * @ctxt: the schema validation context
23502 *
23503 * Free the resources associated to the schema validation context;
23504 * leaves some fields alive intended for reuse of the context.
23505 */
23506static void
23507xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23508{
23509 if (vctxt == NULL)
23510 return;
23511
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023512 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023513 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023514 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023515#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023516 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023517#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023518 if (vctxt->value != NULL) {
23519 xmlSchemaFreeValue(vctxt->value);
23520 vctxt->value = NULL;
23521 }
23522 /*
23523 * Augmented IDC information.
23524 */
23525 if (vctxt->aidcs != NULL) {
23526 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23527 do {
23528 next = cur->next;
23529 xmlFree(cur);
23530 cur = next;
23531 } while (cur != NULL);
23532 vctxt->aidcs = NULL;
23533 }
23534 if (vctxt->idcNodes != NULL) {
23535 int i;
23536 xmlSchemaPSVIIDCNodePtr item;
23537
23538 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023539 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023540 xmlFree(item->keys);
23541 xmlFree(item);
23542 }
23543 xmlFree(vctxt->idcNodes);
23544 vctxt->idcNodes = NULL;
23545 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023546 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023547 * Note that we won't delete the XPath state pool here.
23548 */
23549 if (vctxt->xpathStates != NULL) {
23550 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23551 vctxt->xpathStates = NULL;
23552 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023553 /*
23554 * Attribute info.
23555 */
23556 if (vctxt->nbAttrInfos != 0) {
23557 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023558 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023559 /*
23560 * Element info.
23561 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023562 if (vctxt->elemInfos != NULL) {
23563 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023564 xmlSchemaNodeInfoPtr ei;
23565
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023566 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023567 ei = vctxt->elemInfos[i];
23568 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023569 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023570 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023571 }
23572 }
23573}
23574
23575/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023576 * xmlSchemaFreeValidCtxt:
23577 * @ctxt: the schema validation context
23578 *
23579 * Free the resources associated to the schema validation context
23580 */
23581void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023582xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23583{
Daniel Veillard4255d502002-04-16 15:50:10 +000023584 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023585 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023586 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023587 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023588 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023589 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023590 if (ctxt->idcNodes != NULL) {
23591 int i;
23592 xmlSchemaPSVIIDCNodePtr item;
23593
23594 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023595 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023596 xmlFree(item->keys);
23597 xmlFree(item);
23598 }
23599 xmlFree(ctxt->idcNodes);
23600 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023601 if (ctxt->idcKeys != NULL) {
23602 int i;
23603 for (i = 0; i < ctxt->nbIdcKeys; i++)
23604 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23605 xmlFree(ctxt->idcKeys);
23606 }
23607
23608 if (ctxt->xpathStates != NULL)
23609 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23610 if (ctxt->xpathStatePool != NULL)
23611 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23612
23613 /*
23614 * Augmented IDC information.
23615 */
23616 if (ctxt->aidcs != NULL) {
23617 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23618 do {
23619 next = cur->next;
23620 xmlFree(cur);
23621 cur = next;
23622 } while (cur != NULL);
23623 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023624 if (ctxt->attrInfos != NULL) {
23625 int i;
23626 xmlSchemaAttrInfoPtr attr;
23627
23628 /* Just a paranoid call to the cleanup. */
23629 if (ctxt->nbAttrInfos != 0)
23630 xmlSchemaClearAttrInfos(ctxt);
23631 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23632 attr = ctxt->attrInfos[i];
23633 xmlFree(attr);
23634 }
23635 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023636 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023637 if (ctxt->elemInfos != NULL) {
23638 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023639 xmlSchemaNodeInfoPtr ei;
23640
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023641 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023642 ei = ctxt->elemInfos[i];
23643 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023644 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023645 xmlSchemaClearElemInfo(ei);
23646 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023647 }
23648 xmlFree(ctxt->elemInfos);
23649 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023650 if (ctxt->dict != NULL)
23651 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023652 xmlFree(ctxt);
23653}
23654
23655/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000023656 * xmlSchemaIsValid:
23657 * @ctxt: the schema validation context
23658 *
23659 * Check if any error was detected during validation.
23660 *
23661 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
23662 * of internal error.
23663 */
23664int
23665xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
23666{
23667 if (ctxt == NULL)
23668 return(-1);
23669 return(ctxt->err == 0);
23670}
23671
23672/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023673 * xmlSchemaSetValidErrors:
23674 * @ctxt: a schema validation context
23675 * @err: the error function
23676 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023677 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023678 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023679 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023680 */
23681void
23682xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023683 xmlSchemaValidityErrorFunc err,
23684 xmlSchemaValidityWarningFunc warn, void *ctx)
23685{
Daniel Veillard4255d502002-04-16 15:50:10 +000023686 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023687 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023688 ctxt->error = err;
23689 ctxt->warning = warn;
23690 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023691 if (ctxt->pctxt != NULL)
23692 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023693}
23694
23695/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000023696 * xmlSchemaSetValidStructuredErrors:
23697 * @ctxt: a schema validation context
23698 * @serror: the structured error function
23699 * @ctx: the functions context
23700 *
23701 * Set the structured error callback
23702 */
23703void
23704xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
23705 xmlStructuredErrorFunc serror, void *ctx)
23706{
23707 if (ctxt == NULL)
23708 return;
23709 ctxt->serror = serror;
23710 ctxt->error = NULL;
23711 ctxt->warning = NULL;
23712 ctxt->userData = ctx;
23713}
23714
23715/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023716 * xmlSchemaGetValidErrors:
23717 * @ctxt: a XML-Schema validation context
23718 * @err: the error function result
23719 * @warn: the warning function result
23720 * @ctx: the functions context result
23721 *
23722 * Get the error and warning callback informations
23723 *
23724 * Returns -1 in case of error and 0 otherwise
23725 */
23726int
23727xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23728 xmlSchemaValidityErrorFunc * err,
23729 xmlSchemaValidityWarningFunc * warn, void **ctx)
23730{
23731 if (ctxt == NULL)
23732 return (-1);
23733 if (err != NULL)
23734 *err = ctxt->error;
23735 if (warn != NULL)
23736 *warn = ctxt->warning;
23737 if (ctx != NULL)
23738 *ctx = ctxt->userData;
23739 return (0);
23740}
23741
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023742
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023743/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023744 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023745 * @ctxt: a schema validation context
23746 * @options: a combination of xmlSchemaValidOption
23747 *
23748 * Sets the options to be used during the validation.
23749 *
23750 * Returns 0 in case of success, -1 in case of an
23751 * API error.
23752 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023753int
23754xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23755 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023756
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023757{
23758 int i;
23759
23760 if (ctxt == NULL)
23761 return (-1);
23762 /*
23763 * WARNING: Change the start value if adding to the
23764 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023765 * TODO: Is there an other, more easy to maintain,
23766 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023767 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023768 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023769 if (options & 1<<i)
23770 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023771 }
23772 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023773 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023774}
23775
23776/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023777 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023778 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023779 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023780 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023781 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023782 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023783 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023784int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023785xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023786
23787{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023788 if (ctxt == NULL)
23789 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023790 else
23791 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023792}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023793
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023794static int
23795xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23796{
23797 xmlAttrPtr attr;
23798 int ret = 0;
23799 xmlSchemaNodeInfoPtr ielem = NULL;
23800 xmlNodePtr node, valRoot;
23801 const xmlChar *nsName;
23802
23803 /* DOC VAL TODO: Move this to the start function. */
23804 valRoot = xmlDocGetRootElement(vctxt->doc);
23805 if (valRoot == NULL) {
23806 /* VAL TODO: Error code? */
23807 VERROR(1, NULL, "The document has no document element");
23808 return (1);
23809 }
23810 vctxt->depth = -1;
23811 vctxt->validationRoot = valRoot;
23812 node = valRoot;
23813 while (node != NULL) {
23814 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23815 goto next_sibling;
23816 if (node->type == XML_ELEMENT_NODE) {
23817
23818 /*
23819 * Init the node-info.
23820 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023821 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023822 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23823 goto internal_error;
23824 ielem = vctxt->inode;
23825 ielem->node = node;
23826 ielem->localName = node->name;
23827 if (node->ns != NULL)
23828 ielem->nsName = node->ns->href;
23829 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23830 /*
23831 * Register attributes.
23832 * DOC VAL TODO: We do not register namespace declaration
23833 * attributes yet.
23834 */
23835 vctxt->nbAttrInfos = 0;
23836 if (node->properties != NULL) {
23837 attr = node->properties;
23838 do {
23839 if (attr->ns != NULL)
23840 nsName = attr->ns->href;
23841 else
23842 nsName = NULL;
23843 ret = xmlSchemaValidatorPushAttribute(vctxt,
23844 (xmlNodePtr) attr,
23845 attr->name, nsName, 0,
23846 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23847 if (ret == -1) {
23848 VERROR_INT("xmlSchemaDocWalk",
23849 "calling xmlSchemaValidatorPushAttribute()");
23850 goto internal_error;
23851 }
23852 attr = attr->next;
23853 } while (attr);
23854 }
23855 /*
23856 * Validate the element.
23857 */
23858 ret = xmlSchemaValidateElem(vctxt);
23859 if (ret != 0) {
23860 if (ret == -1) {
23861 VERROR_INT("xmlSchemaDocWalk",
23862 "calling xmlSchemaValidateElem()");
23863 goto internal_error;
23864 }
23865 /*
23866 * Don't stop validation; just skip the content
23867 * of this element.
23868 */
23869 goto leave_node;
23870 }
23871 if ((vctxt->skipDepth != -1) &&
23872 (vctxt->depth >= vctxt->skipDepth))
23873 goto leave_node;
23874 } else if ((node->type == XML_TEXT_NODE) ||
23875 (node->type == XML_CDATA_SECTION_NODE)) {
23876 /*
23877 * Process character content.
23878 */
23879 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23880 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23881 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23882 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23883 if (ret < 0) {
23884 VERROR_INT("xmlSchemaVDocWalk",
23885 "calling xmlSchemaVPushText()");
23886 goto internal_error;
23887 }
23888 /*
23889 * DOC VAL TODO: Should we skip further validation of the
23890 * element content here?
23891 */
23892 } else if ((node->type == XML_ENTITY_NODE) ||
23893 (node->type == XML_ENTITY_REF_NODE)) {
23894 /*
23895 * DOC VAL TODO: What to do with entities?
23896 */
23897 TODO
23898 } else {
23899 goto leave_node;
23900 /*
23901 * DOC VAL TODO: XInclude nodes, etc.
23902 */
23903 }
23904 /*
23905 * Walk the doc.
23906 */
23907 if (node->children != NULL) {
23908 node = node->children;
23909 continue;
23910 }
23911leave_node:
23912 if (node->type == XML_ELEMENT_NODE) {
23913 /*
23914 * Leaving the scope of an element.
23915 */
23916 if (node != vctxt->inode->node) {
23917 VERROR_INT("xmlSchemaVDocWalk",
23918 "element position mismatch");
23919 goto internal_error;
23920 }
23921 ret = xmlSchemaValidatorPopElem(vctxt);
23922 if (ret != 0) {
23923 if (ret < 0) {
23924 VERROR_INT("xmlSchemaVDocWalk",
23925 "calling xmlSchemaValidatorPopElem()");
23926 goto internal_error;
23927 }
23928 }
23929 if (node == valRoot)
23930 goto exit;
23931 }
23932next_sibling:
23933 if (node->next != NULL)
23934 node = node->next;
23935 else {
23936 node = node->parent;
23937 goto leave_node;
23938 }
23939 }
23940
23941exit:
23942 return (ret);
23943internal_error:
23944 return (-1);
23945}
23946
23947static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000023948xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023949 /*
23950 * Some initialization.
23951 */
23952 vctxt->err = 0;
23953 vctxt->nberrors = 0;
23954 vctxt->depth = -1;
23955 vctxt->skipDepth = -1;
23956 /*
23957 * Create a schema + parser if necessary.
23958 */
23959 if (vctxt->schema == NULL) {
23960
23961 if ((vctxt->pctxt == NULL) &&
23962 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
23963 return (-1);
23964
23965 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
23966 if (vctxt->schema == NULL) {
23967 VERROR_INT("xmlSchemaVStartValidation",
23968 "creating a schema");
23969 return (-1);
23970 }
23971 vctxt->xsiAssemble = 1;
23972 } else
23973 vctxt->xsiAssemble = 0;
23974 /*
23975 * Augment the IDC definitions.
23976 */
23977 if (vctxt->schema->idcDef != NULL) {
23978 xmlHashScan(vctxt->schema->idcDef,
23979 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
23980 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000023981 return(0);
23982}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023983
Daniel Veillardf10ae122005-07-10 19:03:16 +000023984static void
23985xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023986 if (vctxt->xsiAssemble) {
23987 if (vctxt->schema != NULL) {
23988 xmlSchemaFree(vctxt->schema);
23989 vctxt->schema = NULL;
23990 }
23991 }
23992 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000023993}
23994
23995static int
23996xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
23997{
23998 int ret = 0;
23999
24000 if (xmlSchemaPreRun(vctxt) < 0)
24001 return(-1);
24002
24003 if (vctxt->doc != NULL) {
24004 /*
24005 * Tree validation.
24006 */
24007 ret = xmlSchemaVDocWalk(vctxt);
24008#ifdef LIBXML_READER_ENABLED
24009 } else if (vctxt->reader != NULL) {
24010 /*
24011 * XML Reader validation.
24012 */
24013#ifdef XML_SCHEMA_READER_ENABLED
24014 ret = xmlSchemaVReaderWalk(vctxt);
24015#endif
24016#endif
24017 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
24018 /*
24019 * SAX validation.
24020 */
24021 ret = xmlParseDocument(vctxt->parserCtxt);
24022 } else {
24023 VERROR_INT("xmlSchemaVStartValidation",
24024 "no instance to validate");
24025 ret = -1;
24026 }
24027
24028 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024029 if (ret == 0)
24030 ret = vctxt->err;
24031 return (ret);
24032}
24033
24034/**
24035 * xmlSchemaValidateOneElement:
24036 * @ctxt: a schema validation context
24037 * @elem: an element node
24038 *
24039 * Validate a branch of a tree, starting with the given @elem.
24040 *
24041 * Returns 0 if the element and its subtree is valid, a positive error
24042 * code number otherwise and -1 in case of an internal or API error.
24043 */
24044int
24045xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24046{
24047 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24048 return (-1);
24049
24050 if (ctxt->schema == NULL)
24051 return (-1);
24052
24053 ctxt->doc = elem->doc;
24054 ctxt->node = elem;
24055 ctxt->validationRoot = elem;
24056 return(xmlSchemaVStart(ctxt));
24057}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024058
Daniel Veillard259f0df2004-08-18 09:13:18 +000024059/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024060 * xmlSchemaValidateDoc:
24061 * @ctxt: a schema validation context
24062 * @doc: a parsed document tree
24063 *
24064 * Validate a document tree in memory.
24065 *
24066 * Returns 0 if the document is schemas valid, a positive error code
24067 * number otherwise and -1 in case of internal or API error.
24068 */
24069int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024070xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24071{
Daniel Veillard4255d502002-04-16 15:50:10 +000024072 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024073 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024074
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024075 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024076 ctxt->node = xmlDocGetRootElement(doc);
24077 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024078 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024079 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24080 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024081 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024082 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024083 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024084 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024085 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024086}
24087
Daniel Veillardcdc82732005-07-08 15:04:06 +000024088
24089/************************************************************************
24090 * *
24091 * Function and data for SAX streaming API *
24092 * *
24093 ************************************************************************/
24094typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24095typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24096
24097struct _xmlSchemaSplitSAXData {
24098 xmlSAXHandlerPtr user_sax;
24099 void *user_data;
24100 xmlSchemaValidCtxtPtr ctxt;
24101 xmlSAXHandlerPtr schemas_sax;
24102};
24103
Daniel Veillard971771e2005-07-09 17:32:57 +000024104#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24105
24106struct _xmlSchemaSAXPlug {
24107 unsigned int magic;
24108
24109 /* the original callbacks informations */
24110 xmlSAXHandlerPtr *user_sax_ptr;
24111 xmlSAXHandlerPtr user_sax;
24112 void **user_data_ptr;
24113 void *user_data;
24114
24115 /* the block plugged back and validation informations */
24116 xmlSAXHandler schemas_sax;
24117 xmlSchemaValidCtxtPtr ctxt;
24118};
24119
Daniel Veillardcdc82732005-07-08 15:04:06 +000024120/* All those functions just bounces to the user provided SAX handlers */
24121static void
24122internalSubsetSplit(void *ctx, const xmlChar *name,
24123 const xmlChar *ExternalID, const xmlChar *SystemID)
24124{
Daniel Veillard971771e2005-07-09 17:32:57 +000024125 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024126 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24127 (ctxt->user_sax->internalSubset != NULL))
24128 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24129 SystemID);
24130}
24131
24132static int
24133isStandaloneSplit(void *ctx)
24134{
Daniel Veillard971771e2005-07-09 17:32:57 +000024135 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024136 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24137 (ctxt->user_sax->isStandalone != NULL))
24138 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24139 return(0);
24140}
24141
24142static int
24143hasInternalSubsetSplit(void *ctx)
24144{
Daniel Veillard971771e2005-07-09 17:32:57 +000024145 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024146 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24147 (ctxt->user_sax->hasInternalSubset != NULL))
24148 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24149 return(0);
24150}
24151
24152static int
24153hasExternalSubsetSplit(void *ctx)
24154{
Daniel Veillard971771e2005-07-09 17:32:57 +000024155 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024156 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24157 (ctxt->user_sax->hasExternalSubset != NULL))
24158 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24159 return(0);
24160}
24161
24162static void
24163externalSubsetSplit(void *ctx, const xmlChar *name,
24164 const xmlChar *ExternalID, const xmlChar *SystemID)
24165{
Daniel Veillard971771e2005-07-09 17:32:57 +000024166 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024167 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24168 (ctxt->user_sax->internalSubset != NULL))
24169 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24170 SystemID);
24171}
24172
24173static xmlParserInputPtr
24174resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24175{
Daniel Veillard971771e2005-07-09 17:32:57 +000024176 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024177 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24178 (ctxt->user_sax->resolveEntity != NULL))
24179 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24180 systemId));
24181 return(NULL);
24182}
24183
24184static xmlEntityPtr
24185getEntitySplit(void *ctx, const xmlChar *name)
24186{
Daniel Veillard971771e2005-07-09 17:32:57 +000024187 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024188 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24189 (ctxt->user_sax->getEntity != NULL))
24190 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24191 return(NULL);
24192}
24193
24194static xmlEntityPtr
24195getParameterEntitySplit(void *ctx, const xmlChar *name)
24196{
Daniel Veillard971771e2005-07-09 17:32:57 +000024197 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024198 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24199 (ctxt->user_sax->getParameterEntity != NULL))
24200 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24201 return(NULL);
24202}
24203
24204
24205static void
24206entityDeclSplit(void *ctx, const xmlChar *name, int type,
24207 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24208{
Daniel Veillard971771e2005-07-09 17:32:57 +000024209 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024210 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24211 (ctxt->user_sax->entityDecl != NULL))
24212 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24213 systemId, content);
24214}
24215
24216static void
24217attributeDeclSplit(void *ctx, const xmlChar * elem,
24218 const xmlChar * name, int type, int def,
24219 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24220{
Daniel Veillard971771e2005-07-09 17:32:57 +000024221 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024222 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24223 (ctxt->user_sax->attributeDecl != NULL)) {
24224 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24225 def, defaultValue, tree);
24226 } else {
24227 xmlFreeEnumeration(tree);
24228 }
24229}
24230
24231static void
24232elementDeclSplit(void *ctx, const xmlChar *name, int type,
24233 xmlElementContentPtr content)
24234{
Daniel Veillard971771e2005-07-09 17:32:57 +000024235 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024236 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24237 (ctxt->user_sax->elementDecl != NULL))
24238 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24239}
24240
24241static void
24242notationDeclSplit(void *ctx, const xmlChar *name,
24243 const xmlChar *publicId, const xmlChar *systemId)
24244{
Daniel Veillard971771e2005-07-09 17:32:57 +000024245 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024246 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24247 (ctxt->user_sax->notationDecl != NULL))
24248 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24249 systemId);
24250}
24251
24252static void
24253unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24254 const xmlChar *publicId, const xmlChar *systemId,
24255 const xmlChar *notationName)
24256{
Daniel Veillard971771e2005-07-09 17:32:57 +000024257 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024258 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24259 (ctxt->user_sax->unparsedEntityDecl != NULL))
24260 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24261 systemId, notationName);
24262}
24263
24264static void
24265setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24266{
Daniel Veillard971771e2005-07-09 17:32:57 +000024267 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024268 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24269 (ctxt->user_sax->setDocumentLocator != NULL))
24270 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24271}
24272
24273static void
24274startDocumentSplit(void *ctx)
24275{
Daniel Veillard971771e2005-07-09 17:32:57 +000024276 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024277 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24278 (ctxt->user_sax->startDocument != NULL))
24279 ctxt->user_sax->startDocument(ctxt->user_data);
24280}
24281
24282static void
24283endDocumentSplit(void *ctx)
24284{
Daniel Veillard971771e2005-07-09 17:32:57 +000024285 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024286 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24287 (ctxt->user_sax->endDocument != NULL))
24288 ctxt->user_sax->endDocument(ctxt->user_data);
24289}
24290
24291static void
24292processingInstructionSplit(void *ctx, const xmlChar *target,
24293 const xmlChar *data)
24294{
Daniel Veillard971771e2005-07-09 17:32:57 +000024295 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024296 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24297 (ctxt->user_sax->processingInstruction != NULL))
24298 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24299}
24300
24301static void
24302commentSplit(void *ctx, const xmlChar *value)
24303{
Daniel Veillard971771e2005-07-09 17:32:57 +000024304 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024305 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24306 (ctxt->user_sax->comment != NULL))
24307 ctxt->user_sax->comment(ctxt->user_data, value);
24308}
24309
24310/*
24311 * Varargs error callbacks to the user application, harder ...
24312 */
24313
Daniel Veillardffa3c742005-07-21 13:24:09 +000024314static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024315warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024316 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024317 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24318 (ctxt->user_sax->warning != NULL)) {
24319 TODO
24320 }
24321}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024322static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024323errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024324 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024325 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24326 (ctxt->user_sax->error != NULL)) {
24327 TODO
24328 }
24329}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024330static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024331fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024332 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024333 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24334 (ctxt->user_sax->fatalError != NULL)) {
24335 TODO
24336 }
24337}
24338
24339/*
24340 * Those are function where both the user handler and the schemas handler
24341 * need to be called.
24342 */
24343static void
24344charactersSplit(void *ctx, const xmlChar *ch, int len)
24345{
Daniel Veillard971771e2005-07-09 17:32:57 +000024346 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024347 if (ctxt == NULL)
24348 return;
24349 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24350 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24351 if (ctxt->ctxt != NULL)
24352 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24353}
24354
24355static void
24356ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24357{
Daniel Veillard971771e2005-07-09 17:32:57 +000024358 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024359 if (ctxt == NULL)
24360 return;
24361 if ((ctxt->user_sax != NULL) &&
24362 (ctxt->user_sax->ignorableWhitespace != NULL))
24363 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24364 if (ctxt->ctxt != NULL)
24365 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24366}
24367
24368static void
24369cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24370{
Daniel Veillard971771e2005-07-09 17:32:57 +000024371 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024372 if (ctxt == NULL)
24373 return;
24374 if ((ctxt->user_sax != NULL) &&
24375 (ctxt->user_sax->ignorableWhitespace != NULL))
24376 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24377 if (ctxt->ctxt != NULL)
24378 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24379}
24380
24381static void
24382referenceSplit(void *ctx, const xmlChar *name)
24383{
Daniel Veillard971771e2005-07-09 17:32:57 +000024384 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024385 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24386 (ctxt->user_sax->reference != NULL))
24387 ctxt->user_sax->reference(ctxt->user_data, name);
24388 if (ctxt->ctxt != NULL)
24389 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24390}
24391
24392static void
24393startElementNsSplit(void *ctx, const xmlChar * localname,
24394 const xmlChar * prefix, const xmlChar * URI,
24395 int nb_namespaces, const xmlChar ** namespaces,
24396 int nb_attributes, int nb_defaulted,
24397 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024398 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024399 if (ctxt == NULL)
24400 return;
24401 if ((ctxt->user_sax != NULL) &&
24402 (ctxt->user_sax->startElementNs != NULL))
24403 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24404 URI, nb_namespaces, namespaces,
24405 nb_attributes, nb_defaulted,
24406 attributes);
24407 if (ctxt->ctxt != NULL)
24408 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24409 URI, nb_namespaces, namespaces,
24410 nb_attributes, nb_defaulted,
24411 attributes);
24412}
24413
24414static void
24415endElementNsSplit(void *ctx, const xmlChar * localname,
24416 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024417 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024418 if (ctxt == NULL)
24419 return;
24420 if ((ctxt->user_sax != NULL) &&
24421 (ctxt->user_sax->endElementNs != NULL))
24422 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24423 if (ctxt->ctxt != NULL)
24424 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24425}
24426
Daniel Veillard4255d502002-04-16 15:50:10 +000024427/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024428 * xmlSchemaSAXPlug:
24429 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024430 * @sax: a pointer to the original xmlSAXHandlerPtr
24431 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024432 *
24433 * Plug a SAX based validation layer in a SAX parsing event flow.
24434 * The original @saxptr and @dataptr data are replaced by new pointers
24435 * but the calls to the original will be maintained.
24436 *
24437 * Returns a pointer to a data structure needed to unplug the validation layer
24438 * or NULL in case of errors.
24439 */
24440xmlSchemaSAXPlugPtr
24441xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24442 xmlSAXHandlerPtr *sax, void **user_data)
24443{
24444 xmlSchemaSAXPlugPtr ret;
24445 xmlSAXHandlerPtr old_sax;
24446
24447 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24448 return(NULL);
24449
24450 /*
24451 * We only allow to plug into SAX2 event streams
24452 */
24453 old_sax = *sax;
24454 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24455 return(NULL);
24456 if ((old_sax != NULL) &&
24457 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24458 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24459 return(NULL);
24460
24461 /*
24462 * everything seems right allocate the local data needed for that layer
24463 */
24464 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24465 if (ret == NULL) {
24466 return(NULL);
24467 }
24468 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24469 ret->magic = XML_SAX_PLUG_MAGIC;
24470 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24471 ret->ctxt = ctxt;
24472 ret->user_sax_ptr = sax;
24473 ret->user_sax = old_sax;
24474 if (old_sax == NULL) {
24475 /*
24476 * go direct, no need for the split block and functions.
24477 */
24478 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24479 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24480 /*
24481 * Note that we use the same text-function for both, to prevent
24482 * the parser from testing for ignorable whitespace.
24483 */
24484 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24485 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24486
24487 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24488 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24489
24490 ret->user_data = ctxt;
24491 *user_data = ctxt;
24492 } else {
24493 /*
24494 * for each callback unused by Schemas initialize it to the Split
24495 * routine only if non NULL in the user block, this can speed up
24496 * things at the SAX level.
24497 */
24498 if (old_sax->internalSubset != NULL)
24499 ret->schemas_sax.internalSubset = internalSubsetSplit;
24500 if (old_sax->isStandalone != NULL)
24501 ret->schemas_sax.isStandalone = isStandaloneSplit;
24502 if (old_sax->hasInternalSubset != NULL)
24503 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24504 if (old_sax->hasExternalSubset != NULL)
24505 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24506 if (old_sax->resolveEntity != NULL)
24507 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24508 if (old_sax->getEntity != NULL)
24509 ret->schemas_sax.getEntity = getEntitySplit;
24510 if (old_sax->entityDecl != NULL)
24511 ret->schemas_sax.entityDecl = entityDeclSplit;
24512 if (old_sax->notationDecl != NULL)
24513 ret->schemas_sax.notationDecl = notationDeclSplit;
24514 if (old_sax->attributeDecl != NULL)
24515 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24516 if (old_sax->elementDecl != NULL)
24517 ret->schemas_sax.elementDecl = elementDeclSplit;
24518 if (old_sax->unparsedEntityDecl != NULL)
24519 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24520 if (old_sax->setDocumentLocator != NULL)
24521 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24522 if (old_sax->startDocument != NULL)
24523 ret->schemas_sax.startDocument = startDocumentSplit;
24524 if (old_sax->endDocument != NULL)
24525 ret->schemas_sax.endDocument = endDocumentSplit;
24526 if (old_sax->processingInstruction != NULL)
24527 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24528 if (old_sax->comment != NULL)
24529 ret->schemas_sax.comment = commentSplit;
24530 if (old_sax->warning != NULL)
24531 ret->schemas_sax.warning = warningSplit;
24532 if (old_sax->error != NULL)
24533 ret->schemas_sax.error = errorSplit;
24534 if (old_sax->fatalError != NULL)
24535 ret->schemas_sax.fatalError = fatalErrorSplit;
24536 if (old_sax->getParameterEntity != NULL)
24537 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24538 if (old_sax->externalSubset != NULL)
24539 ret->schemas_sax.externalSubset = externalSubsetSplit;
24540
24541 /*
24542 * the 6 schemas callback have to go to the splitter functions
24543 * Note that we use the same text-function for ignorableWhitespace
24544 * if possible, to prevent the parser from testing for ignorable
24545 * whitespace.
24546 */
24547 ret->schemas_sax.characters = charactersSplit;
24548 if ((old_sax->ignorableWhitespace != NULL) &&
24549 (old_sax->ignorableWhitespace != old_sax->characters))
24550 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24551 else
24552 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24553 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24554 ret->schemas_sax.reference = referenceSplit;
24555 ret->schemas_sax.startElementNs = startElementNsSplit;
24556 ret->schemas_sax.endElementNs = endElementNsSplit;
24557
24558 ret->user_data_ptr = user_data;
24559 ret->user_data = *user_data;
24560 *user_data = ret;
24561 }
24562
24563 /*
24564 * plug the pointers back.
24565 */
24566 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024567 ctxt->sax = *sax;
24568 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24569 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024570 return(ret);
24571}
24572
24573/**
24574 * xmlSchemaSAXUnplug:
24575 * @plug: a data structure returned by xmlSchemaSAXPlug
24576 *
24577 * Unplug a SAX based validation layer in a SAX parsing event flow.
24578 * The original pointers used in the call are restored.
24579 *
24580 * Returns 0 in case of success and -1 in case of failure.
24581 */
24582int
24583xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24584{
24585 xmlSAXHandlerPtr *sax;
24586 void **user_data;
24587
24588 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24589 return(-1);
24590 plug->magic = 0;
24591
Daniel Veillardf10ae122005-07-10 19:03:16 +000024592 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024593 /* restore the data */
24594 sax = plug->user_sax_ptr;
24595 *sax = plug->user_sax;
24596 if (plug->user_sax != NULL) {
24597 user_data = plug->user_data_ptr;
24598 *user_data = plug->user_data;
24599 }
24600
24601 /* free and return */
24602 xmlFree(plug);
24603 return(0);
24604}
24605
24606/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024607 * xmlSchemaValidateStream:
24608 * @ctxt: a schema validation context
24609 * @input: the input to use for reading the data
24610 * @enc: an optional encoding information
24611 * @sax: a SAX handler for the resulting events
24612 * @user_data: the context to provide to the SAX handler.
24613 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024614 * Validate an input based on a flow of SAX event from the parser
24615 * and forward the events to the @sax handler with the provided @user_data
24616 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024617 *
24618 * Returns 0 if the document is schemas valid, a positive error code
24619 * number otherwise and -1 in case of internal or API error.
24620 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024621int
Daniel Veillard4255d502002-04-16 15:50:10 +000024622xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024623 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24624 xmlSAXHandlerPtr sax, void *user_data)
24625{
Daniel Veillard971771e2005-07-09 17:32:57 +000024626 xmlSchemaSAXPlugPtr plug = NULL;
24627 xmlSAXHandlerPtr old_sax = NULL;
24628 xmlParserCtxtPtr pctxt = NULL;
24629 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024630 int ret;
24631
Daniel Veillard4255d502002-04-16 15:50:10 +000024632 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024633 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024634
Daniel Veillardcdc82732005-07-08 15:04:06 +000024635 /*
24636 * prepare the parser
24637 */
24638 pctxt = xmlNewParserCtxt();
24639 if (pctxt == NULL)
24640 return (-1);
24641 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000024642 pctxt->sax = sax;
24643 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024644#if 0
24645 if (options)
24646 xmlCtxtUseOptions(pctxt, options);
24647#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024648 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024649
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024650 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024651 if (inputStream == NULL) {
24652 ret = -1;
24653 goto done;
24654 }
24655 inputPush(pctxt, inputStream);
24656 ctxt->parserCtxt = pctxt;
24657 ctxt->input = input;
24658
24659 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000024660 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000024661 */
Daniel Veillard971771e2005-07-09 17:32:57 +000024662 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
24663 if (plug == NULL) {
24664 ret = -1;
24665 goto done;
24666 }
24667 ctxt->input = input;
24668 ctxt->enc = enc;
24669 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024670 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24671 ret = xmlSchemaVStart(ctxt);
24672
24673 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24674 ret = ctxt->parserCtxt->errNo;
24675 if (ret == 0)
24676 ret = 1;
24677 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024678
24679done:
Daniel Veillard971771e2005-07-09 17:32:57 +000024680 ctxt->parserCtxt = NULL;
24681 ctxt->sax = NULL;
24682 ctxt->input = NULL;
24683 if (plug != NULL) {
24684 xmlSchemaSAXUnplug(plug);
24685 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024686 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000024687 if (pctxt != NULL) {
24688 pctxt->sax = old_sax;
24689 xmlFreeParserCtxt(pctxt);
24690 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024691 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024692}
24693
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024694/**
24695 * xmlSchemaValidateFile:
24696 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024697 * @filename: the URI of the instance
24698 * @options: a future set of options, currently unused
24699 *
24700 * Do a schemas validation of the given resource, it will use the
24701 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024702 *
24703 * Returns 0 if the document is valid, a positive error code
24704 * number otherwise and -1 in case of an internal or API error.
24705 */
24706int
24707xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024708 const char * filename,
24709 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024710{
Daniel Veillard81562d22005-06-15 13:27:56 +000024711#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024712 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024713 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024714
24715 if ((ctxt == NULL) || (filename == NULL))
24716 return (-1);
24717
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024718 input = xmlParserInputBufferCreateFilename(filename,
24719 XML_CHAR_ENCODING_NONE);
24720 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024721 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024722 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24723 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024724 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024725#else
24726 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024727#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024728}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024729
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024730#define bottom_xmlschemas
24731#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024732#endif /* LIBXML_SCHEMAS_ENABLED */