blob: d17c3bdac47a2431ea0ef249b7e50a48322e6007 [file] [log] [blame]
Daniel Veillard4255d502002-04-16 15:50:10 +00001/*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
4 *
5 * See Copyright for the status of this software.
6 *
7 * Daniel Veillard <veillard@redhat.com>
8 */
9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000069#define DUMP_CONTENT_MODEL
70
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000071#define XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000103static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +0000104 "complex type";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000105static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000106 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000107#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000108static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000109 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000110#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000111
Daniel Veillard4255d502002-04-16 15:50:10 +0000112#define IS_SCHEMA(node, type) \
113 ((node != NULL) && (node->ns != NULL) && \
114 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
115 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
116
Daniel Veillardc0826a72004-08-10 14:17:33 +0000117#define FREE_AND_NULL(str) \
118 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000119 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120 str = NULL; \
121 }
122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000123#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000124 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
125 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000126
127#define IS_COMPLEX_TYPE(item) \
128 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
129 (item->builtInType == XML_SCHEMAS_ANYTYPE))
130
131#define IS_SIMPLE_TYPE(item) \
132 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
133 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000134 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000135
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000136#define IS_ANY_SIMPLE_TYPE(item) \
137 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000138 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000139
140#define IS_NOT_TYPEFIXED(item) \
141 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
142 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
143
144#define HAS_COMPLEX_CONTENT(item) \
145 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
146 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
147 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
148
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000149#define HAS_SIMPLE_CONTENT(item) \
150 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
151 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
152
153#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
154
155#define IS_PARTICLE_EMPTIABLE(item) \
156 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000158#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000160#define GET_LIST_ITEM_TYPE(item) item->subtypes
161
162#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
163#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
164#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
165
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000166#define IS_MODEL_GROUP(item) \
167 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
168 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
169 (item->type == XML_SCHEMA_TYPE_ALL))
170
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000171#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
172
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000173#define ELEM_TYPE(item) item->subtypes
174
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000175#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
176
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000177#define SUBST_GROUP_AFF(item) item->refDecl
178
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000179#if 0
180#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
181#endif
182
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000183#define SUBSET_RESTRICTION 1<<0
184#define SUBSET_EXTENSION 1<<1
185#define SUBSET_SUBSTITUTION 1<<2
186#define SUBSET_LIST 1<<3
187#define SUBSET_UNION 1<<4
188
Daniel Veillard4255d502002-04-16 15:50:10 +0000189#define XML_SCHEMAS_PARSE_ERROR 1
190
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000191#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
192
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000193typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
194typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000195
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000198typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000199
200typedef struct _xmlSchemaItemList xmlSchemaItemList;
201typedef xmlSchemaItemList *xmlSchemaItemListPtr;
202
203struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000204 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 int nbItems; /* used for dynamic addition of schemata */
206 int sizeItems; /* used for dynamic addition of schemata */
207};
208
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000209typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
210typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
211struct _xmlSchemaAbstractCtxt {
212 int type;
213};
214
215#define XML_SCHEMA_CTXT_PARSER 1
216#define XML_SCHEMA_CTXT_VALIDATOR 2
217
Daniel Veillard4255d502002-04-16 15:50:10 +0000218struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000219 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000220 void *userData; /* user specific data block */
221 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
222 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000223 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000225 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000226
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000227 xmlSchemaPtr topschema; /* The main schema */
228 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
229
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000230 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000231 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000232 int counter;
233
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000234 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000235 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000236 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000237
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000238 const char *buffer;
239 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000240
Daniel Veillard4255d502002-04-16 15:50:10 +0000241 /*
242 * Used to build complex element content models
243 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000244 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000245 xmlAutomataStatePtr start;
246 xmlAutomataStatePtr end;
247 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000248
249 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000250 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000251 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
252 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000253 xmlSchemaAssemblePtr assemble;
254 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000255 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000256 const xmlChar **localImports; /* list of locally imported namespaces */
257 int sizeLocalImports;
258 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000259 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000260 int isS4S;
Daniel Veillard4255d502002-04-16 15:50:10 +0000261};
262
Daniel Veillard4255d502002-04-16 15:50:10 +0000263#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000264#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000265#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000266#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000267#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000268#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
269#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000270#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000271#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000272#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
273#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
274#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
275#define XML_SCHEMAS_ATTR_WILD_SKIP 13
276#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
277#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
278#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
279#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000280
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000281/**
282 * xmlSchemaBasicItem:
283 *
284 * The abstract base type for schema components.
285 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000286typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
287typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
288struct _xmlSchemaBasicItem {
289 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000290};
291
292/**
293 * xmlSchemaAnnotItem:
294 *
295 * The abstract base type for annotated schema components.
296 * (Extends xmlSchemaBasicItem)
297 */
298typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
299typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
300struct _xmlSchemaAnnotItem {
301 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000302 xmlSchemaAnnotPtr annot;
303};
304
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000305/**
306 * xmlSchemaTreeItem:
307 *
308 * The abstract base type for tree-like structured schema components.
309 * (Extends xmlSchemaAnnotItem)
310 */
311typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
312typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
313struct _xmlSchemaTreeItem {
314 xmlSchemaTypeType type;
315 xmlSchemaAnnotPtr annot;
316 xmlSchemaTreeItemPtr next;
317 xmlSchemaTreeItemPtr children;
318};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000319
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000320/**
321 * xmlSchemaQNameRef:
322 *
323 * A component reference item (not a schema component)
324 * (Extends xmlSchemaBasicItem)
325 */
326typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
327typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
328struct _xmlSchemaQNameRef {
329 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000330 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000331 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000332 const xmlChar *name;
333 const xmlChar *targetNamespace;
334};
335
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000336/**
337 * xmlSchemaParticle:
338 *
339 * A particle component.
340 * (Extends xmlSchemaTreeItem)
341 */
342typedef struct _xmlSchemaParticle xmlSchemaParticle;
343typedef xmlSchemaParticle *xmlSchemaParticlePtr;
344struct _xmlSchemaParticle {
345 xmlSchemaTypeType type;
346 xmlSchemaAnnotPtr annot;
347 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
348 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
349 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000350 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000351 xmlNodePtr node;
352};
353
354/**
355 * xmlSchemaModelGroup:
356 *
357 * A model group component.
358 * (Extends xmlSchemaTreeItem)
359 */
360typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
361typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
362struct _xmlSchemaModelGroup {
363 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
364 xmlSchemaAnnotPtr annot;
365 xmlSchemaTreeItemPtr next; /* not used */
366 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
367 xmlNodePtr node;
368};
369
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000370#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000371/**
372 * xmlSchemaModelGroupDef:
373 *
374 * A model group definition component.
375 * (Extends xmlSchemaTreeItem)
376 */
377typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
378typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
379struct _xmlSchemaModelGroupDef {
380 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
381 xmlSchemaAnnotPtr annot;
382 xmlSchemaTreeItemPtr next; /* not used */
383 xmlSchemaTreeItemPtr children; /* the "model group" */
384 const xmlChar *name;
385 const xmlChar *targetNamespace;
386 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000387 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000388};
389
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000390typedef struct _xmlSchemaIDC xmlSchemaIDC;
391typedef xmlSchemaIDC *xmlSchemaIDCPtr;
392
393/**
394 * xmlSchemaIDCSelect:
395 *
396 * The identity-constraint "field" and "selector" item, holding the
397 * XPath expression.
398 */
399typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
400typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000401struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000402 xmlSchemaIDCSelectPtr next;
403 xmlSchemaIDCPtr idc;
404 int index; /* an index position if significant for IDC key-sequences */
405 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000406 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000407};
408
409/**
410 * xmlSchemaIDC:
411 *
412 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000413 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000414 */
415
416struct _xmlSchemaIDC {
417 xmlSchemaTypeType type;
418 xmlSchemaAnnotPtr annot;
419 xmlSchemaIDCPtr next;
420 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000421 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000422 const xmlChar *targetNamespace;
423 xmlSchemaIDCSelectPtr selector;
424 xmlSchemaIDCSelectPtr fields;
425 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000426 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000427};
428
429/**
430 * xmlSchemaIDCAug:
431 *
432 * The augmented IDC information used for validation.
433 */
434typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
435typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
436struct _xmlSchemaIDCAug {
437 xmlSchemaIDCAugPtr next; /* next in a list */
438 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000439 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000440 tables need to be bubbled upwards */
441};
442
443/**
444 * xmlSchemaPSVIIDCKeySequence:
445 *
446 * The key sequence of a node table item.
447 */
448typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
449typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
450struct _xmlSchemaPSVIIDCKey {
451 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000452 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453};
454
455/**
456 * xmlSchemaPSVIIDCNode:
457 *
458 * The node table item of a node table.
459 */
460typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
461typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
462struct _xmlSchemaPSVIIDCNode {
463 xmlNodePtr node;
464 xmlSchemaPSVIIDCKeyPtr *keys;
465};
466
467/**
468 * xmlSchemaPSVIIDCBinding:
469 *
470 * The identity-constraint binding item of the [identity-constraint table].
471 */
472typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
473typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
474struct _xmlSchemaPSVIIDCBinding {
475 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
476 xmlSchemaIDCPtr definition; /* the IDC definition */
477 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
478 int nbNodes; /* number of entries in the node table */
479 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000480 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000481 table */
482 /* int nbKeys; number of keys in each key-sequence */
483};
484
485#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
486#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
487
488#define XPATH_STATE_OBJ_MATCHES -2
489#define XPATH_STATE_OBJ_BLOCKED -3
490
491typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
492typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
493
494/**
495 * xmlSchemaIDCStateObj:
496 *
497 * The state object used to evaluate XPath expressions.
498 */
499typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
500typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
501struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000502 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000503 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000504 int depth; /* depth of creation */
505 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506 int nbHistory;
507 int sizeHistory;
508 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
509 matcher */
510 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000511 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000512};
513
514#define IDC_MATCHER 0
515
516/**
517 * xmlSchemaIDCMatcher:
518 *
519 * Used to IDC selectors (and fields) successively.
520 */
521struct _xmlSchemaIDCMatcher {
522 int type;
523 int depth; /* the tree depth at creation time */
524 xmlSchemaIDCMatcherPtr next; /* next in the list */
525 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
526 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
527 elements */
528 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000529 int targetDepth;
530};
531
532/*
533* Element info flags.
534*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000535#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
536#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
537#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
538#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
539
540#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
541#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
542#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
543
544#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
545#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
546#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
547#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000548
549/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000550 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 *
552 * Holds information of an element node.
553 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000554struct _xmlSchemaNodeInfo {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000555 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000556 int nodeType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000557 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 const xmlChar *nsName;
559 const xmlChar *value;
560 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000561 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000562 int flags; /* combination of node info flags */
563 int valNeeded;
564 int normVal;
565
566 xmlSchemaElementPtr decl; /* the element/attribute declaration */
567 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
569 for the scope element*/
570 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
571 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000572 xmlRegExecCtxtPtr regexCtxt;
573
574 const xmlChar **nsBindings; /* Namespace bindings on this element */
575 int nbNsBindings;
576 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000577};
578
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000579/*
580* @metaType values of xmlSchemaAttrInfo.
581*/
582#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
583#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
584#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
585#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
586#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000588typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
589typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
590struct _xmlSchemaAttrInfo {
591 xmlNodePtr node;
592 int nodeType;
593 const xmlChar *localName;
594 const xmlChar *nsName;
595 const xmlChar *value;
596 xmlSchemaValPtr val; /* the pre-computed value if any */
597 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
598 int flags; /* combination of node info flags */
599
600 xmlSchemaAttributePtr decl; /* the attribute declaration */
601 xmlSchemaAttributePtr use; /* the attribute use */
602 int state;
603 int metaType;
604 const xmlChar *vcValue; /* the value constraint value */
605 xmlSchemaNodeInfoPtr parent;
606};
607
608
609#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000610/**
611 * xmlSchemaValidCtxt:
612 *
613 * A Schemas validation context
614 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000615struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000616 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 void *userData; /* user specific data block */
618 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000619 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000620 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000621
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000622 xmlSchemaPtr schema; /* The schema in use */
623 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000624 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000625 xmlCharEncoding enc;
626 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000627 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000628 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000629
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000630 int err;
631 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000632
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000633 xmlNodePtr node;
634 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000635 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000636
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000637 xmlRegExecCtxtPtr regexp;
638 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000639
Daniel Veillardc0826a72004-08-10 14:17:33 +0000640 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000641 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000642 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000643 xmlSchemaParserCtxtPtr pctxt;
644 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000645
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000646 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000647 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000648 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000649 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000650
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000651 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
652
653 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
654 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000655
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000656 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
657 int nbIdcNodes;
658 int sizeIdcNodes;
659
660 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
661 int nbIdcKeys;
662 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000663
664 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000665
666 xmlDictPtr dict;
667
Daniel Veillard39e5c892005-07-03 22:48:50 +0000668#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000669 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000670#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000671
672 xmlSchemaAttrInfoPtr *attrInfos;
673 int nbAttrInfos;
674 int sizeAttrInfos;
675
676 int skipDepth;
Daniel Veillard4255d502002-04-16 15:50:10 +0000677};
678
Daniel Veillard1d913862003-11-21 00:28:39 +0000679/*
680 * These are the entries in the schemas importSchemas hash table
681 */
682typedef struct _xmlSchemaImport xmlSchemaImport;
683typedef xmlSchemaImport *xmlSchemaImportPtr;
684struct _xmlSchemaImport {
685 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000686 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000687 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000688 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000689};
Daniel Veillard4255d502002-04-16 15:50:10 +0000690
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000691/*
692 * These are the entries associated to includes in a schemas
693 */
694typedef struct _xmlSchemaInclude xmlSchemaInclude;
695typedef xmlSchemaInclude *xmlSchemaIncludePtr;
696struct _xmlSchemaInclude {
697 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000698 const xmlChar *schemaLocation;
699 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000700 const xmlChar *origTargetNamespace;
701 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000702};
703
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000704/**
705 * xmlSchemaSubstGroup:
706 *
707 *
708 */
709typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
710typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
711struct _xmlSchemaSubstGroup {
712 xmlSchemaElementPtr head;
713 xmlSchemaItemListPtr members;
714};
715
Daniel Veillard4255d502002-04-16 15:50:10 +0000716/************************************************************************
717 * *
718 * Some predeclarations *
719 * *
720 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000721
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000722static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
723 xmlSchemaPtr schema,
724 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000725static void
726xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
727 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000728static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000729xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
730static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000731xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
732 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000733static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000734xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
735 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000736static void
737xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000738static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000739xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000740static xmlSchemaTreeItemPtr
741xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
742 xmlNodePtr node, xmlSchemaTypeType type,
743 int withParticle);
744static const xmlChar *
745xmlSchemaCompTypeToString(xmlSchemaTypeType type);
746static xmlSchemaTypeLinkPtr
747xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000748static void
749xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
750 const char *funcName,
751 const char *message);
752static int
753xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
754 xmlSchemaTypePtr baseType,
755 int subset);
756static void
757xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
758 xmlSchemaParserCtxtPtr ctxt,
759 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000760
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000761/************************************************************************
762 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000763 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000764 * *
765 ************************************************************************/
766
767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000768 * xmlSchemaCompTypeToString:
769 * @type: the type of the schema item
770 *
771 * Returns the component name of a schema item.
772 */
773static const xmlChar *
774xmlSchemaCompTypeToString(xmlSchemaTypeType type)
775{
776 switch (type) {
777 case XML_SCHEMA_TYPE_SIMPLE:
778 return(BAD_CAST "simple type definition");
779 case XML_SCHEMA_TYPE_COMPLEX:
780 return(BAD_CAST "complex type definition");
781 case XML_SCHEMA_TYPE_ELEMENT:
782 return(BAD_CAST "element declaration");
783 case XML_SCHEMA_TYPE_ATTRIBUTE:
784 return(BAD_CAST "attribute declaration");
785 case XML_SCHEMA_TYPE_GROUP:
786 return(BAD_CAST "model group definition");
787 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
788 return(BAD_CAST "attribute group definition");
789 case XML_SCHEMA_TYPE_NOTATION:
790 return(BAD_CAST "notation declaration");
791 case XML_SCHEMA_TYPE_SEQUENCE:
792 return(BAD_CAST "model group (sequence)");
793 case XML_SCHEMA_TYPE_CHOICE:
794 return(BAD_CAST "model group (choice)");
795 case XML_SCHEMA_TYPE_ALL:
796 return(BAD_CAST "model group (all)");
797 case XML_SCHEMA_TYPE_PARTICLE:
798 return(BAD_CAST "particle");
799 default:
800 return(BAD_CAST "Not a schema component");
801 }
802}
803
804/**
805 * xmlSchemaGetComponentNode:
806 * @item: a schema component
807 *
808 * Returns node associated with the schema component.
809 * NOTE that such a node need not be available; plus, a component's
810 * node need not to reflect the component directly, since there is no
811 * one-to-one relationship between the XML Schema representation and
812 * the component representation.
813 */
814static xmlNodePtr
815xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
816{
817 switch (item->type) {
818 case XML_SCHEMA_TYPE_ELEMENT:
819 return (((xmlSchemaElementPtr) item)->node);
820 case XML_SCHEMA_TYPE_ATTRIBUTE:
821 return (((xmlSchemaAttributePtr) item)->node);
822 case XML_SCHEMA_TYPE_COMPLEX:
823 case XML_SCHEMA_TYPE_SIMPLE:
824 return (((xmlSchemaTypePtr) item)->node);
825 case XML_SCHEMA_TYPE_ANY:
826 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
827 return (((xmlSchemaWildcardPtr) item)->node);
828 case XML_SCHEMA_TYPE_PARTICLE:
829 return (((xmlSchemaParticlePtr) item)->node);
830 case XML_SCHEMA_TYPE_SEQUENCE:
831 case XML_SCHEMA_TYPE_CHOICE:
832 case XML_SCHEMA_TYPE_ALL:
833 return (((xmlSchemaModelGroupPtr) item)->node);
834 case XML_SCHEMA_TYPE_GROUP:
835 return (((xmlSchemaModelGroupDefPtr) item)->node);
836 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
837 return (((xmlSchemaAttributeGroupPtr) item)->node);
838 case XML_SCHEMA_TYPE_IDC_UNIQUE:
839 case XML_SCHEMA_TYPE_IDC_KEY:
840 case XML_SCHEMA_TYPE_IDC_KEYREF:
841 return (((xmlSchemaIDCPtr) item)->node);
842 default:
843 return (NULL);
844 }
845}
846
847#if 0
848/**
849 * xmlSchemaGetNextComponent:
850 * @item: a schema component
851 *
852 * Returns the next sibling of the schema component.
853 */
854static xmlSchemaBasicItemPtr
855xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
856{
857 switch (item->type) {
858 case XML_SCHEMA_TYPE_ELEMENT:
859 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
860 case XML_SCHEMA_TYPE_ATTRIBUTE:
861 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
862 case XML_SCHEMA_TYPE_COMPLEX:
863 case XML_SCHEMA_TYPE_SIMPLE:
864 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
865 case XML_SCHEMA_TYPE_ANY:
866 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
867 return (NULL);
868 case XML_SCHEMA_TYPE_PARTICLE:
869 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
870 case XML_SCHEMA_TYPE_SEQUENCE:
871 case XML_SCHEMA_TYPE_CHOICE:
872 case XML_SCHEMA_TYPE_ALL:
873 return (NULL);
874 case XML_SCHEMA_TYPE_GROUP:
875 return (NULL);
876 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
877 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
878 case XML_SCHEMA_TYPE_IDC_UNIQUE:
879 case XML_SCHEMA_TYPE_IDC_KEY:
880 case XML_SCHEMA_TYPE_IDC_KEYREF:
881 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
882 default:
883 return (NULL);
884 }
885}
886#endif
887
888/**
889 * xmlSchemaGetAttrName:
890 * @attr: the attribute declaration/use
891 *
892 * Returns the name of the attribute; if the attribute
893 * is a reference, the name of the referenced global type will be returned.
894 */
895static const xmlChar *
896xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
897{
898 if (attr->ref != NULL)
899 return(attr->ref);
900 else
901 return(attr->name);
902}
903
904/**
905 * xmlSchemaGetAttrTargetNsURI:
906 * @type: the type (element or attribute)
907 *
908 * Returns the target namespace URI of the type; if the type is a reference,
909 * the target namespace of the referenced type will be returned.
910 */
911static const xmlChar *
912xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
913{
914 if (attr->ref != NULL)
915 return (attr->refNs);
916 else
917 return(attr->targetNamespace);
918}
919
920/**
921 * xmlSchemaFormatQName:
922 * @buf: the string buffer
923 * @namespaceName: the namespace name
924 * @localName: the local name
925 *
926 * Returns the given QName in the format "{namespaceName}localName" or
927 * just "localName" if @namespaceName is NULL.
928 *
929 * Returns the localName if @namespaceName is NULL, a formatted
930 * string otherwise.
931 */
932static const xmlChar*
933xmlSchemaFormatQName(xmlChar **buf,
934 const xmlChar *namespaceName,
935 const xmlChar *localName)
936{
937 FREE_AND_NULL(*buf)
938 if (namespaceName == NULL)
939 return(localName);
940
941 *buf = xmlStrdup(BAD_CAST "{");
942 *buf = xmlStrcat(*buf, namespaceName);
943 *buf = xmlStrcat(*buf, BAD_CAST "}");
944 *buf = xmlStrcat(*buf, localName);
945
946 return ((const xmlChar *) *buf);
947}
948
949static const xmlChar*
950xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
951{
952 if (ns != NULL)
953 return (xmlSchemaFormatQName(buf, ns->href, localName));
954 else
955 return (xmlSchemaFormatQName(buf, NULL, localName));
956}
957
958static const xmlChar *
959xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
960{
961 switch (item->type) {
962 case XML_SCHEMA_TYPE_ELEMENT:
963 return (((xmlSchemaElementPtr) item)->name);
964 case XML_SCHEMA_TYPE_ATTRIBUTE:
965 return (((xmlSchemaAttributePtr) item)->name);
966 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
967 return (((xmlSchemaAttributeGroupPtr) item)->name);
968 case XML_SCHEMA_TYPE_BASIC:
969 case XML_SCHEMA_TYPE_SIMPLE:
970 case XML_SCHEMA_TYPE_COMPLEX:
971 return (((xmlSchemaTypePtr) item)->name);
972 case XML_SCHEMA_TYPE_GROUP:
973 return (((xmlSchemaModelGroupDefPtr) item)->name);
974 case XML_SCHEMA_TYPE_IDC_KEY:
975 case XML_SCHEMA_TYPE_IDC_UNIQUE:
976 case XML_SCHEMA_TYPE_IDC_KEYREF:
977 return (((xmlSchemaIDCPtr) item)->name);
978 default:
979 /*
980 * Other components cannot have names.
981 */
982 break;
983 }
984 return (NULL);
985}
986
987static const xmlChar *
988xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
989{
990 switch (item->type) {
991 case XML_SCHEMA_TYPE_ELEMENT:
992 return (((xmlSchemaElementPtr) item)->targetNamespace);
993 case XML_SCHEMA_TYPE_ATTRIBUTE:
994 return (((xmlSchemaAttributePtr) item)->targetNamespace);
995 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
996 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
997 case XML_SCHEMA_TYPE_BASIC:
998 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
999 case XML_SCHEMA_TYPE_SIMPLE:
1000 case XML_SCHEMA_TYPE_COMPLEX:
1001 return (((xmlSchemaTypePtr) item)->targetNamespace);
1002 case XML_SCHEMA_TYPE_GROUP:
1003 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1004 case XML_SCHEMA_TYPE_IDC_KEY:
1005 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1006 case XML_SCHEMA_TYPE_IDC_KEYREF:
1007 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1008 default:
1009 /*
1010 * Other components cannot have names.
1011 */
1012 break;
1013 }
1014 return (NULL);
1015}
1016
1017static const xmlChar*
1018xmlSchemaGetComponentQName(xmlChar **buf,
1019 void *item)
1020{
1021 return (xmlSchemaFormatQName(buf,
1022 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1023 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1024}
1025
1026/**
1027 * xmlSchemaWildcardPCToString:
1028 * @pc: the type of processContents
1029 *
1030 * Returns a string representation of the type of
1031 * processContents.
1032 */
1033static const xmlChar *
1034xmlSchemaWildcardPCToString(int pc)
1035{
1036 switch (pc) {
1037 case XML_SCHEMAS_ANY_SKIP:
1038 return (BAD_CAST "skip");
1039 case XML_SCHEMAS_ANY_LAX:
1040 return (BAD_CAST "lax");
1041 case XML_SCHEMAS_ANY_STRICT:
1042 return (BAD_CAST "strict");
1043 default:
1044 return (BAD_CAST "invalid process contents");
1045 }
1046}
1047
1048/**
1049 * xmlSchemaGetCanonValueWhtspExt:
1050 * @val: the precomputed value
1051 * @retValue: the returned value
1052 * @ws: the whitespace type of the value
1053 *
1054 * Get a the cononical representation of the value.
1055 * The caller has to free the returned retValue.
1056 *
1057 * Returns 0 if the value could be built and -1 in case of
1058 * API errors or if the value type is not supported yet.
1059 */
1060static int
1061xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1062 xmlSchemaWhitespaceValueType ws,
1063 xmlChar **retValue)
1064{
1065 int list;
1066 xmlSchemaValType valType;
1067 const xmlChar *value, *value2 = NULL;
1068
1069
1070 if ((retValue == NULL) || (val == NULL))
1071 return (-1);
1072 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1073 *retValue = NULL;
1074 do {
1075 value = NULL;
1076 valType = xmlSchemaGetValType(val);
1077 switch (valType) {
1078 case XML_SCHEMAS_STRING:
1079 case XML_SCHEMAS_NORMSTRING:
1080 case XML_SCHEMAS_ANYSIMPLETYPE:
1081 value = xmlSchemaValueGetAsString(val);
1082 if (value != NULL) {
1083 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1084 value2 = xmlSchemaCollapseString(value);
1085 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1086 value2 = xmlSchemaWhiteSpaceReplace(value);
1087 if (value2 != NULL)
1088 value = value2;
1089 }
1090 break;
1091 default:
1092 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1093 if (value2 != NULL)
1094 xmlFree((xmlChar *) value2);
1095 goto internal_error;
1096 }
1097 value = value2;
1098 }
1099 if (*retValue == NULL)
1100 if (value == NULL) {
1101 if (! list)
1102 *retValue = xmlStrdup(BAD_CAST "");
1103 } else
1104 *retValue = xmlStrdup(value);
1105 else if (value != NULL) {
1106 /* List. */
1107 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1108 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1109 }
1110 FREE_AND_NULL(value2)
1111 val = xmlSchemaValueGetNext(val);
1112 } while (val != NULL);
1113
1114 return (0);
1115internal_error:
1116 if (*retValue != NULL)
1117 xmlFree((xmlChar *) (*retValue));
1118 if (value2 != NULL)
1119 xmlFree((xmlChar *) value2);
1120 return (-1);
1121}
1122
1123/**
1124 * xmlSchemaFormatItemForReport:
1125 * @buf: the string buffer
1126 * @itemDes: the designation of the item
1127 * @itemName: the name of the item
1128 * @item: the item as an object
1129 * @itemNode: the node of the item
1130 * @local: the local name
1131 * @parsing: if the function is used during the parse
1132 *
1133 * Returns a representation of the given item used
1134 * for error reports.
1135 *
1136 * The following order is used to build the resulting
1137 * designation if the arguments are not NULL:
1138 * 1a. If itemDes not NULL -> itemDes
1139 * 1b. If (itemDes not NULL) and (itemName not NULL)
1140 * -> itemDes + itemName
1141 * 2. If the preceding was NULL and (item not NULL) -> item
1142 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1143 *
1144 * If the itemNode is an attribute node, the name of the attribute
1145 * will be appended to the result.
1146 *
1147 * Returns the formatted string and sets @buf to the resulting value.
1148 */
1149static xmlChar*
1150xmlSchemaFormatItemForReport(xmlChar **buf,
1151 const xmlChar *itemDes,
1152 xmlSchemaTypePtr item,
1153 xmlNodePtr itemNode)
1154{
1155 xmlChar *str = NULL;
1156 int named = 1;
1157
1158 if (*buf != NULL) {
1159 xmlFree(*buf);
1160 *buf = NULL;
1161 }
1162
1163 if (itemDes != NULL) {
1164 *buf = xmlStrdup(itemDes);
1165 } else if (item != NULL) {
1166 switch (item->type) {
1167 case XML_SCHEMA_TYPE_BASIC:
1168 if (VARIETY_ATOMIC(item))
1169 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1170 else if (VARIETY_LIST(item))
1171 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1172 else if (VARIETY_UNION(item))
1173 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1174 else
1175 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1176 *buf = xmlStrcat(*buf, item->name);
1177 *buf = xmlStrcat(*buf, BAD_CAST "'");
1178 break;
1179 case XML_SCHEMA_TYPE_SIMPLE:
1180 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1181 *buf = xmlStrdup(BAD_CAST"");
1182 } else {
1183 *buf = xmlStrdup(BAD_CAST "local ");
1184 }
1185 if (VARIETY_ATOMIC(item))
1186 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1187 else if (VARIETY_LIST(item))
1188 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1189 else if (VARIETY_UNION(item))
1190 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1191 else
1192 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1193 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1194 *buf = xmlStrcat(*buf, BAD_CAST " '");
1195 *buf = xmlStrcat(*buf, item->name);
1196 *buf = xmlStrcat(*buf, BAD_CAST "'");
1197 }
1198 break;
1199 case XML_SCHEMA_TYPE_COMPLEX:
1200 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1201 *buf = xmlStrdup(BAD_CAST "");
1202 else
1203 *buf = xmlStrdup(BAD_CAST "local ");
1204 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1205 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1206 *buf = xmlStrcat(*buf, BAD_CAST " '");
1207 *buf = xmlStrcat(*buf, item->name);
1208 *buf = xmlStrcat(*buf, BAD_CAST "'");
1209 }
1210 break;
1211 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1212 xmlSchemaAttributePtr attr;
1213
1214 attr = (xmlSchemaAttributePtr) item;
1215 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1216 (attr->ref == NULL)) {
1217 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1218 *buf = xmlStrcat(*buf, BAD_CAST " '");
1219 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1220 attr->targetNamespace, attr->name));
1221 FREE_AND_NULL(str)
1222 *buf = xmlStrcat(*buf, BAD_CAST "'");
1223 } else {
1224 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1225 *buf = xmlStrcat(*buf, BAD_CAST " '");
1226 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1227 attr->refNs, attr->ref));
1228 FREE_AND_NULL(str)
1229 *buf = xmlStrcat(*buf, BAD_CAST "'");
1230 }
1231 }
1232 break;
1233 case XML_SCHEMA_TYPE_ELEMENT: {
1234 xmlSchemaElementPtr elem;
1235
1236 elem = (xmlSchemaElementPtr) item;
1237 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1238 (elem->ref == NULL)) {
1239 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1240 *buf = xmlStrcat(*buf, BAD_CAST " '");
1241 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1242 elem->targetNamespace, elem->name));
1243 *buf = xmlStrcat(*buf, BAD_CAST "'");
1244 }
1245 }
1246 break;
1247 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1248 case XML_SCHEMA_TYPE_IDC_KEY:
1249 case XML_SCHEMA_TYPE_IDC_KEYREF:
1250 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1251 *buf = xmlStrdup(BAD_CAST "unique '");
1252 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1253 *buf = xmlStrdup(BAD_CAST "key '");
1254 else
1255 *buf = xmlStrdup(BAD_CAST "keyRef '");
1256 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1257 *buf = xmlStrcat(*buf, BAD_CAST "'");
1258 break;
1259 case XML_SCHEMA_TYPE_ANY:
1260 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1261 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1262 ((xmlSchemaWildcardPtr) item)->processContents));
1263 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1264 break;
1265 case XML_SCHEMA_FACET_MININCLUSIVE:
1266 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1267 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1268 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1269 case XML_SCHEMA_FACET_TOTALDIGITS:
1270 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1271 case XML_SCHEMA_FACET_PATTERN:
1272 case XML_SCHEMA_FACET_ENUMERATION:
1273 case XML_SCHEMA_FACET_WHITESPACE:
1274 case XML_SCHEMA_FACET_LENGTH:
1275 case XML_SCHEMA_FACET_MAXLENGTH:
1276 case XML_SCHEMA_FACET_MINLENGTH:
1277 *buf = xmlStrdup(BAD_CAST "facet '");
1278 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1279 *buf = xmlStrcat(*buf, BAD_CAST "'");
1280 break;
1281 case XML_SCHEMA_TYPE_NOTATION:
1282 *buf = xmlStrdup(BAD_CAST "notation");
1283 break;
1284 case XML_SCHEMA_TYPE_GROUP: {
1285 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1286 *buf = xmlStrcat(*buf, BAD_CAST " '");
1287 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1288 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1289 ((xmlSchemaModelGroupDefPtr) item)->name));
1290 *buf = xmlStrcat(*buf, BAD_CAST "'");
1291 FREE_AND_NULL(str)
1292 }
1293 break;
1294 case XML_SCHEMA_TYPE_SEQUENCE:
1295 case XML_SCHEMA_TYPE_CHOICE:
1296 case XML_SCHEMA_TYPE_ALL:
1297 case XML_SCHEMA_TYPE_PARTICLE:
1298 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1299 break;
1300 default:
1301 named = 0;
1302 }
1303 } else
1304 named = 0;
1305
1306 if ((named == 0) && (itemNode != NULL)) {
1307 xmlNodePtr elem;
1308
1309 if (itemNode->type == XML_ATTRIBUTE_NODE)
1310 elem = itemNode->parent;
1311 else
1312 elem = itemNode;
1313 *buf = xmlStrdup(BAD_CAST "Element '");
1314 if (elem->ns != NULL) {
1315 *buf = xmlStrcat(*buf,
1316 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1317 FREE_AND_NULL(str)
1318 } else
1319 *buf = xmlStrcat(*buf, elem->name);
1320 *buf = xmlStrcat(*buf, BAD_CAST "'");
1321
1322 }
1323 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1324 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1325 if (itemNode->ns != NULL) {
1326 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1327 itemNode->ns->href, itemNode->name));
1328 FREE_AND_NULL(str)
1329 } else
1330 *buf = xmlStrcat(*buf, itemNode->name);
1331 *buf = xmlStrcat(*buf, BAD_CAST "'");
1332 }
1333 FREE_AND_NULL(str)
1334
1335 return (*buf);
1336}
1337
1338/**
1339 * xmlSchemaFormatFacetEnumSet:
1340 * @buf: the string buffer
1341 * @type: the type holding the enumeration facets
1342 *
1343 * Builds a string consisting of all enumeration elements.
1344 *
1345 * Returns a string of all enumeration elements.
1346 */
1347static const xmlChar *
1348xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1349 xmlChar **buf, xmlSchemaTypePtr type)
1350{
1351 xmlSchemaFacetPtr facet;
1352 xmlSchemaWhitespaceValueType ws;
1353 xmlChar *value = NULL;
1354 int res;
1355
1356 if (*buf != NULL)
1357 xmlFree(*buf);
1358 *buf = NULL;
1359
1360 do {
1361 /*
1362 * Use the whitespace type of the base type.
1363 */
1364 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1365 for (facet = type->facets; facet != NULL; facet = facet->next) {
1366 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1367 continue;
1368 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1369 ws, &value);
1370 if (res == -1) {
1371 xmlSchemaInternalErr(actxt,
1372 "xmlSchemaFormatFacetEnumSet",
1373 "compute the canonical lexical representation");
1374 if (*buf != NULL)
1375 xmlFree(*buf);
1376 *buf = NULL;
1377 return (NULL);
1378 }
1379 if (*buf == NULL)
1380 *buf = xmlStrdup(BAD_CAST "'");
1381 else
1382 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1383 *buf = xmlStrcat(*buf, BAD_CAST value);
1384 *buf = xmlStrcat(*buf, BAD_CAST "'");
1385 if (value != NULL) {
1386 xmlFree((xmlChar *)value);
1387 value = NULL;
1388 }
1389 }
1390 type = type->baseType;
1391 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1392
1393 return ((const xmlChar *) *buf);
1394}
1395
1396/************************************************************************
1397 * *
1398 * Error functions *
1399 * *
1400 ************************************************************************/
1401
1402#if 0
1403static void
1404xmlSchemaErrMemory(const char *msg)
1405{
1406 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1407 msg);
1408}
1409#endif
1410
1411/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001412 * xmlSchemaPErrMemory:
1413 * @node: a context node
1414 * @extra: extra informations
1415 *
1416 * Handle an out of memory condition
1417 */
1418static void
1419xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1420 const char *extra, xmlNodePtr node)
1421{
1422 if (ctxt != NULL)
1423 ctxt->nberrors++;
1424 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1425 extra);
1426}
1427
1428/**
1429 * xmlSchemaPErr:
1430 * @ctxt: the parsing context
1431 * @node: the context node
1432 * @error: the error code
1433 * @msg: the error message
1434 * @str1: extra data
1435 * @str2: extra data
1436 *
1437 * Handle a parser error
1438 */
1439static void
1440xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1441 const char *msg, const xmlChar * str1, const xmlChar * str2)
1442{
1443 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001444 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001445 void *data = NULL;
1446
1447 if (ctxt != NULL) {
1448 ctxt->nberrors++;
1449 channel = ctxt->error;
1450 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001451 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001452 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001453 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001454 error, XML_ERR_ERROR, NULL, 0,
1455 (const char *) str1, (const char *) str2, NULL, 0, 0,
1456 msg, str1, str2);
1457}
1458
1459/**
1460 * xmlSchemaPErr2:
1461 * @ctxt: the parsing context
1462 * @node: the context node
1463 * @node: the current child
1464 * @error: the error code
1465 * @msg: the error message
1466 * @str1: extra data
1467 * @str2: extra data
1468 *
1469 * Handle a parser error
1470 */
1471static void
1472xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1473 xmlNodePtr child, int error,
1474 const char *msg, const xmlChar * str1, const xmlChar * str2)
1475{
1476 if (child != NULL)
1477 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1478 else
1479 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1480}
1481
Daniel Veillard01fa6152004-06-29 17:04:39 +00001482
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001483/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001484 * xmlSchemaPErrExt:
1485 * @ctxt: the parsing context
1486 * @node: the context node
1487 * @error: the error code
1488 * @strData1: extra data
1489 * @strData2: extra data
1490 * @strData3: extra data
1491 * @msg: the message
1492 * @str1: extra parameter for the message display
1493 * @str2: extra parameter for the message display
1494 * @str3: extra parameter for the message display
1495 * @str4: extra parameter for the message display
1496 * @str5: extra parameter for the message display
1497 *
1498 * Handle a parser error
1499 */
1500static void
1501xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1502 const xmlChar * strData1, const xmlChar * strData2,
1503 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1504 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1505 const xmlChar * str5)
1506{
1507
1508 xmlGenericErrorFunc channel = NULL;
1509 xmlStructuredErrorFunc schannel = NULL;
1510 void *data = NULL;
1511
1512 if (ctxt != NULL) {
1513 ctxt->nberrors++;
1514 channel = ctxt->error;
1515 data = ctxt->userData;
1516 schannel = ctxt->serror;
1517 }
1518 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1519 error, XML_ERR_ERROR, NULL, 0,
1520 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001521 (const char *) strData3, 0, 0, msg, str1, str2,
1522 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001523}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001524
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001525/************************************************************************
1526 * *
1527 * Allround error functions *
1528 * *
1529 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001530
1531/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001532 * xmlSchemaVTypeErrMemory:
1533 * @node: a context node
1534 * @extra: extra informations
1535 *
1536 * Handle an out of memory condition
1537 */
1538static void
1539xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1540 const char *extra, xmlNodePtr node)
1541{
1542 if (ctxt != NULL) {
1543 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001544 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001545 }
1546 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1547 extra);
1548}
1549
1550/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001551 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001552 * @ctxt: the validation context
1553 * @node: the context node
1554 * @error: the error code
1555 * @msg: the error message
1556 * @str1: extra data
1557 * @str2: extra data
1558 * @str3: extra data
1559 *
1560 * Handle a validation error
1561 */
1562static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001563xmlSchemaErr3(xmlSchemaAbstractCtxtPtr ctxt,
1564 int error, xmlNodePtr node, const char *msg,
1565 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001566{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001567 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001568 xmlGenericErrorFunc channel = NULL;
1569 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001570
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001571 if (ctxt != NULL) {
1572 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1573 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001574 int line = 0;
1575 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001576
1577 vctxt->nberrors++;
1578 vctxt->err = error;
1579 channel = vctxt->error;
1580 schannel = vctxt->serror;
1581 data = vctxt->userData;
1582 if ((node == NULL) && (vctxt->depth >= 0) &&
Daniel Veillard971771e2005-07-09 17:32:57 +00001583 (vctxt->inode != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001584 node = vctxt->inode->node;
Daniel Veillard971771e2005-07-09 17:32:57 +00001585 }
1586 if ((node == NULL) && (vctxt->parserCtxt != NULL) &&
1587 (vctxt->parserCtxt->input != NULL)) {
1588 file = vctxt->parserCtxt->input->filename;
1589 line = vctxt->parserCtxt->input->line;
1590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001591 __xmlRaiseError(schannel, channel, data, ctxt,
1592 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001593 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001594 (const char *) str1, (const char *) str2,
1595 (const char *) str3, 0, 0, msg, str1, str2, str3);
1596
1597 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1598 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1599
1600 pctxt->nberrors++;
1601 pctxt->err = error;
1602 channel = pctxt->error;
1603 schannel = pctxt->serror;
1604 data = pctxt->userData;
1605 __xmlRaiseError(schannel, channel, data, ctxt,
1606 node, XML_FROM_SCHEMASP,
1607 error, XML_ERR_ERROR, NULL, 0,
1608 (const char *) str1, (const char *) str2,
1609 (const char *) str3, 0, 0, msg, str1, str2, str3);
1610 } else {
1611 TODO
1612 }
1613 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001614}
1615
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001616static void
1617xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1618 int error, xmlNodePtr node, const char *msg,
1619 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001620{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001621 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001622}
1623
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001624static xmlChar *
1625xmlSchemaFormatNodeForError(xmlChar ** msg,
1626 xmlSchemaAbstractCtxtPtr actxt,
1627 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001628{
1629 xmlChar *str = NULL;
1630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001631 if (node != NULL) {
1632 /*
1633 * Work on tree nodes.
1634 */
1635 if (node->type == XML_ATTRIBUTE_NODE) {
1636 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001637
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001638 *msg = xmlStrdup(BAD_CAST "Element '");
1639 if (elem->ns != NULL)
1640 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1641 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001642 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001643 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1644 NULL, elem->name));
1645 FREE_AND_NULL(str);
1646 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1647 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1648 } else {
1649 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001650 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001651 if (node->ns != NULL)
1652 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1653 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001654 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001655 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1656 NULL, node->name));
1657 FREE_AND_NULL(str);
1658 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1659 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1660 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1661 /*
1662 * Work on node infos.
1663 */
1664 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1665 xmlSchemaNodeInfoPtr ielem =
1666 vctxt->elemInfos[vctxt->depth];
1667
1668 *msg = xmlStrdup(BAD_CAST "Element '");
1669 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1670 ielem->nsName, ielem->localName));
1671 FREE_AND_NULL(str);
1672 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1673 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1674 } else {
1675 *msg = xmlStrdup(BAD_CAST "Element '");
1676 }
1677 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1678 vctxt->inode->nsName, vctxt->inode->localName));
1679 FREE_AND_NULL(str);
1680 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1681 } else {
1682 TODO
1683 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001684 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001685 /*
1686 * VAL TODO: The output of the given schema component is currently
1687 * disabled.
1688 */
1689#if 0
1690 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1691 *msg = xmlStrcat(*msg, BAD_CAST " [");
1692 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1693 NULL, type, NULL, 0));
1694 FREE_AND_NULL(str)
1695 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001697#endif
1698 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001699}
1700
Daniel Veillardc0826a72004-08-10 14:17:33 +00001701static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001702xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1703 const char *funcName,
1704 const char *message)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001705{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001706 xmlChar *msg = NULL;
1707
1708 msg = xmlStrdup(BAD_CAST "Internal error: ");
1709 msg = xmlStrcat(msg, BAD_CAST funcName);
1710 msg = xmlStrcat(msg, BAD_CAST ", ");
1711 msg = xmlStrcat(msg, BAD_CAST message);
1712 msg = xmlStrcat(msg, BAD_CAST ".\n");
1713
1714 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1715 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
1716 (const char *) msg, NULL, NULL);
1717
1718 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
1719 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
1720 (const char *) msg, NULL, NULL);
1721
1722 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001723}
1724
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001725static void
1726xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1727 xmlParserErrors error,
1728 xmlNodePtr node,
1729 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1730 const char *message,
1731 const xmlChar *str1,
1732 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001733{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001734 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001735
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001736 xmlSchemaFormatNodeForError(&msg, actxt, node);
1737 msg = xmlStrcat(msg, (const xmlChar *) message);
1738 msg = xmlStrcat(msg, BAD_CAST ".\n");
1739 xmlSchemaErr(actxt, error, node,
1740 (const char *) msg, str1, str2);
1741 FREE_AND_NULL(msg)
1742}
1743
1744static int
1745xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1746 xmlNodePtr node)
1747{
1748 if (node != NULL)
1749 return (node->type);
1750 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1751 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1752 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1753 return (-1);
1754}
1755
1756static int
1757xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1758{
1759 switch (item->type) {
1760 case XML_SCHEMA_TYPE_COMPLEX:
1761 case XML_SCHEMA_TYPE_SIMPLE:
1762 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1763 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001764 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001765 case XML_SCHEMA_TYPE_GROUP:
1766 return (1);
1767 case XML_SCHEMA_TYPE_ELEMENT:
1768 if ( ((xmlSchemaElementPtr) item)->flags &
1769 XML_SCHEMAS_ELEM_GLOBAL)
1770 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001771 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001772 case XML_SCHEMA_TYPE_ATTRIBUTE:
1773 if ( ((xmlSchemaAttributePtr) item)->flags &
1774 XML_SCHEMAS_ATTR_GLOBAL)
1775 return(1);
1776 break;
1777 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001778 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001779 return(1);
1780 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001781 return (0);
1782}
1783
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001784static void
1785xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1786 xmlParserErrors error,
1787 xmlNodePtr node,
1788 const xmlChar *value,
1789 xmlSchemaTypePtr type,
1790 int displayValue)
1791{
1792 xmlChar *msg = NULL;
1793
1794 xmlSchemaFormatNodeForError(&msg, actxt, node);
1795
1796 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1797 XML_ATTRIBUTE_NODE))
1798 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1799 else
1800 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1801 "value of ");
1802
1803 if (! xmlSchemaIsGlobalItem(type))
1804 msg = xmlStrcat(msg, BAD_CAST "the local ");
1805 else
1806 msg = xmlStrcat(msg, BAD_CAST "the ");
1807
1808 if (VARIETY_ATOMIC(type))
1809 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1810 else if (VARIETY_LIST(type))
1811 msg = xmlStrcat(msg, BAD_CAST "list type");
1812 else if (VARIETY_UNION(type))
1813 msg = xmlStrcat(msg, BAD_CAST "union type");
1814
1815 if (xmlSchemaIsGlobalItem(type)) {
1816 xmlChar *str = NULL;
1817 msg = xmlStrcat(msg, BAD_CAST " '");
1818 if (type->builtInType != 0) {
1819 msg = xmlStrcat(msg, BAD_CAST "xs:");
1820 msg = xmlStrcat(msg, type->name);
1821 } else
1822 msg = xmlStrcat(msg,
1823 xmlSchemaFormatQName(&str,
1824 type->targetNamespace, type->name));
1825 msg = xmlStrcat(msg, BAD_CAST "'");
1826 FREE_AND_NULL(str);
1827 }
1828 msg = xmlStrcat(msg, BAD_CAST ".\n");
1829 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1830 XML_ATTRIBUTE_NODE))
1831 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1832 else
1833 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
1834 FREE_AND_NULL(msg)
1835}
1836
Daniel Veillardc0826a72004-08-10 14:17:33 +00001837static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001838xmlSchemaFormatErrorNodeQName(xmlChar ** str,
1839 xmlSchemaNodeInfoPtr ni,
1840 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001841{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001842 if (node != NULL) {
1843 if (node->ns != NULL)
1844 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
1845 else
1846 return (xmlSchemaFormatQName(str, NULL, node->name));
1847 } else if (ni != NULL)
1848 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
1849 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001850}
1851
Daniel Veillardc0826a72004-08-10 14:17:33 +00001852static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001853xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
1854 xmlParserErrors error,
1855 xmlSchemaAttrInfoPtr ni,
1856 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001857{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001858 xmlChar *msg = NULL, *str = NULL;
1859
1860 xmlSchemaFormatNodeForError(&msg, actxt, node);
1861 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
1862 xmlSchemaErr(actxt, error, node, (const char *) msg,
1863 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
1864 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001865 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001866 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001867}
1868
Daniel Veillardc0826a72004-08-10 14:17:33 +00001869static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001870xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1871 xmlParserErrors error,
1872 xmlNodePtr node,
1873 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001874 const char *message,
1875 int nbval,
1876 int nbneg,
1877 xmlChar **values)
1878{
1879 xmlChar *str = NULL, *msg = NULL;
1880 xmlChar *localName, *nsName;
1881 const xmlChar *cur, *end;
1882 int i;
1883
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001884 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001885 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001886 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001887 /*
1888 * Note that is does not make sense to report that we have a
1889 * wildcard here, since the wildcard might be unfolded into
1890 * multiple transitions.
1891 */
1892 if (nbval + nbneg > 0) {
1893 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001894 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001895 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001896 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001897 nsName = NULL;
1898
1899 for (i = 0; i < nbval + nbneg; i++) {
1900 cur = values[i];
1901 /*
1902 * Get the local name.
1903 */
1904 localName = NULL;
1905
1906 end = cur;
1907 if (*end == '*') {
1908 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001909 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001910 } else {
1911 while ((*end != 0) && (*end != '|'))
1912 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001913 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001914 }
1915 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00001916 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001917 /*
1918 * Skip "*|*" if they come with negated expressions, since
1919 * they represent the same negated wildcard.
1920 */
1921 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1922 /*
1923 * Get the namespace name.
1924 */
1925 cur = end;
1926 if (*end == '*') {
1927 nsName = xmlStrdup(BAD_CAST "{*}");
1928 } else {
1929 while (*end != 0)
1930 end++;
1931
1932 if (i >= nbval)
1933 nsName = xmlStrdup(BAD_CAST "{##other:");
1934 else
1935 nsName = xmlStrdup(BAD_CAST "{");
1936
1937 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1938 nsName = xmlStrcat(nsName, BAD_CAST "}");
1939 }
1940 str = xmlStrcat(str, BAD_CAST nsName);
1941 FREE_AND_NULL(nsName)
1942 } else {
1943 FREE_AND_NULL(localName);
1944 continue;
1945 }
1946 }
1947 str = xmlStrcat(str, BAD_CAST localName);
1948 FREE_AND_NULL(localName);
1949
1950 if (i < nbval + nbneg -1)
1951 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001952 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001953 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001954 msg = xmlStrcat(msg, BAD_CAST str);
1955 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001956 } else
1957 msg = xmlStrcat(msg, BAD_CAST "\n");
1958 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001959 xmlFree(msg);
1960}
1961
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001962static void
1963xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
1964 xmlParserErrors error,
1965 xmlNodePtr node,
1966 const xmlChar *value,
1967 unsigned long length,
1968 xmlSchemaTypePtr type,
1969 xmlSchemaFacetPtr facet,
1970 const char *message,
1971 const xmlChar *str1,
1972 const xmlChar *str2)
1973{
1974 xmlChar *str = NULL, *msg = NULL;
1975 xmlSchemaTypeType facetType;
1976 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
1977
1978 xmlSchemaFormatNodeForError(&msg, actxt, node);
1979 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1980 facetType = XML_SCHEMA_FACET_ENUMERATION;
1981 /*
1982 * If enumerations are validated, one must not expect the
1983 * facet to be given.
1984 */
1985 } else
1986 facetType = facet->type;
1987 msg = xmlStrcat(msg, BAD_CAST "[");
1988 msg = xmlStrcat(msg, BAD_CAST "facet '");
1989 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
1990 msg = xmlStrcat(msg, BAD_CAST "'] ");
1991 if (message == NULL) {
1992 /*
1993 * Use a default message.
1994 */
1995 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1996 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1997 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1998
1999 char len[25], actLen[25];
2000
2001 /* FIXME, TODO: What is the max expected string length of the
2002 * this value?
2003 */
2004 if (nodeType == XML_ATTRIBUTE_NODE)
2005 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2006 else
2007 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2008
2009 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2010 snprintf(actLen, 24, "%lu", length);
2011
2012 if (facetType == XML_SCHEMA_FACET_LENGTH)
2013 msg = xmlStrcat(msg,
2014 BAD_CAST "this differs from the allowed length of '%s'.\n");
2015 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2016 msg = xmlStrcat(msg,
2017 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2018 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2019 msg = xmlStrcat(msg,
2020 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2021
2022 if (nodeType == XML_ATTRIBUTE_NODE)
2023 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2024 value, (const xmlChar *) actLen, (const xmlChar *) len);
2025 else
2026 xmlSchemaErr(actxt, error, node, (const char *) msg,
2027 (const xmlChar *) actLen, (const xmlChar *) len);
2028
2029 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2030 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2031 "of the set {%s}.\n");
2032 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2033 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2034 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2035 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2036 "by the pattern '%s'.\n");
2037 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2038 facet->value);
2039 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2040 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2041 "minimum value allowed ('%s').\n");
2042 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2043 facet->value);
2044 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2045 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2046 "maximum value allowed ('%s').\n");
2047 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2048 facet->value);
2049 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2050 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2051 "'%s'.\n");
2052 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2053 facet->value);
2054 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2055 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2056 "'%s'.\n");
2057 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2058 facet->value);
2059 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2060 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2061 "digits than are allowed ('%s').\n");
2062 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2063 facet->value);
2064 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2065 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2066 "digits than are allowed ('%s').\n");
2067 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2068 facet->value);
2069 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2070 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2071 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2072 } else {
2073 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2074 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2075 }
2076 } else {
2077 msg = xmlStrcat(msg, (const xmlChar *) message);
2078 msg = xmlStrcat(msg, BAD_CAST ".\n");
2079 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2080 }
2081 FREE_AND_NULL(str)
2082 xmlFree(msg);
2083}
2084
2085#define VERROR(err, type, msg) \
2086 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2087
2088#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2089
2090#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
2091
2092#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2093
2094
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002095/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002096 * xmlSchemaPMissingAttrErr:
2097 * @ctxt: the schema validation context
2098 * @ownerDes: the designation of the owner
2099 * @ownerName: the name of the owner
2100 * @ownerItem: the owner as a schema object
2101 * @ownerElem: the owner as an element node
2102 * @node: the parent element node of the missing attribute node
2103 * @type: the corresponding type of the attribute node
2104 *
2105 * Reports an illegal attribute.
2106 */
2107static void
2108xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002109 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002110 xmlSchemaTypePtr ownerItem,
2111 xmlNodePtr ownerElem,
2112 const char *name,
2113 const char *message)
2114{
2115 xmlChar *des = NULL;
2116
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002117 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2118
Daniel Veillardc0826a72004-08-10 14:17:33 +00002119 if (message != NULL)
2120 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002121 else
2122 xmlSchemaPErr(ctxt, ownerElem, error,
2123 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002124 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002125 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002126}
2127
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002128
Daniel Veillardc0826a72004-08-10 14:17:33 +00002129/**
2130 * xmlSchemaPResCompAttrErr:
2131 * @ctxt: the schema validation context
2132 * @error: the error code
2133 * @ownerDes: the designation of the owner
2134 * @ownerItem: the owner as a schema object
2135 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002136 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002137 * @refName: the referenced local name
2138 * @refURI: the referenced namespace URI
2139 * @message: optional message
2140 *
2141 * Used to report QName attribute values that failed to resolve
2142 * to schema components.
2143 */
2144static void
2145xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002146 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002147 xmlSchemaTypePtr ownerItem,
2148 xmlNodePtr ownerElem,
2149 const char *name,
2150 const xmlChar *refName,
2151 const xmlChar *refURI,
2152 xmlSchemaTypeType refType,
2153 const char *refTypeStr)
2154{
2155 xmlChar *des = NULL, *strA = NULL;
2156
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002157 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002158 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002159 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2160 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002161 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002162 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2163 "%s.\n", BAD_CAST des, BAD_CAST name,
2164 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002165 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002166 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002167 FREE_AND_NULL(strA)
2168}
2169
William M. Brack2f2a6632004-08-20 23:09:47 +00002170/**
2171 * xmlSchemaPCustomAttrErr:
2172 * @ctxt: the schema parser context
2173 * @error: the error code
2174 * @ownerDes: the designation of the owner
2175 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002176 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002177 *
2178 * Reports an illegal attribute during the parse.
2179 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002180static void
2181xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002182 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002183 xmlChar **ownerDes,
2184 xmlSchemaTypePtr ownerItem,
2185 xmlAttrPtr attr,
2186 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002187{
2188 xmlChar *des = NULL;
2189
2190 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002191 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002192 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002193 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002194 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002195 } else
2196 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002197 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002198 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002199 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2200 if (ownerDes == NULL)
2201 FREE_AND_NULL(des);
2202}
2203
2204/**
2205 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002206 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002207 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002208 * @ownerDes: the designation of the attribute's owner
2209 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002210 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002211 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002212 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002213 */
2214static void
2215xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002216 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002217 xmlChar **ownerDes,
2218 xmlSchemaTypePtr ownerItem,
2219 xmlAttrPtr attr)
2220{
2221 xmlChar *des = NULL, *strA = NULL;
2222
2223 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002224 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002225 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002226 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002227 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002228 } else
2229 des = *ownerDes;
2230 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2231 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2232 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002233 if (ownerDes == NULL)
2234 FREE_AND_NULL(des);
2235 FREE_AND_NULL(strA);
2236}
2237
William M. Brack2f2a6632004-08-20 23:09:47 +00002238/**
2239 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002240 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002241 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002242 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002243 * @itemElem: the node of the schema item
2244 *
2245 * Creates a designation for an item.
2246 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002247static void
2248xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002249 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002250 xmlSchemaTypePtr item,
2251 xmlNodePtr itemElem)
2252{
2253 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002254 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002255 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002256 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002257 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002258 } else
2259 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002260}
2261
William M. Brack2f2a6632004-08-20 23:09:47 +00002262/**
2263 * xmlSchemaPCustomErr:
2264 * @ctxt: the schema parser context
2265 * @error: the error code
2266 * @itemDes: the designation of the schema item
2267 * @item: the schema item
2268 * @itemElem: the node of the schema item
2269 * @message: the error message
2270 * @str1: an optional param for the error message
2271 * @str2: an optional param for the error message
2272 * @str3: an optional param for the error message
2273 *
2274 * Reports an error during parsing.
2275 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002276static void
2277xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002278 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002279 xmlChar **itemDes,
2280 xmlSchemaTypePtr item,
2281 xmlNodePtr itemElem,
2282 const char *message,
2283 const xmlChar *str1,
2284 const xmlChar *str2,
2285 const xmlChar *str3)
2286{
2287 xmlChar *des = NULL, *msg = NULL;
2288
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002289 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002290 msg = xmlStrdup(BAD_CAST "%s: ");
2291 msg = xmlStrcat(msg, (const xmlChar *) message);
2292 msg = xmlStrcat(msg, BAD_CAST ".\n");
2293 if ((itemElem == NULL) && (item != NULL))
2294 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002295 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002296 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2297 if (itemDes == NULL)
2298 FREE_AND_NULL(des);
2299 FREE_AND_NULL(msg);
2300}
2301
William M. Brack2f2a6632004-08-20 23:09:47 +00002302/**
2303 * xmlSchemaPCustomErr:
2304 * @ctxt: the schema parser context
2305 * @error: the error code
2306 * @itemDes: the designation of the schema item
2307 * @item: the schema item
2308 * @itemElem: the node of the schema item
2309 * @message: the error message
2310 * @str1: the optional param for the error message
2311 *
2312 * Reports an error during parsing.
2313 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002314static void
2315xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002316 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002317 xmlChar **itemDes,
2318 xmlSchemaTypePtr item,
2319 xmlNodePtr itemElem,
2320 const char *message,
2321 const xmlChar *str1)
2322{
2323 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2324 str1, NULL, NULL);
2325}
2326
William M. Brack2f2a6632004-08-20 23:09:47 +00002327/**
2328 * xmlSchemaPAttrUseErr:
2329 * @ctxt: the schema parser context
2330 * @error: the error code
2331 * @itemDes: the designation of the schema type
2332 * @item: the schema type
2333 * @itemElem: the node of the schema type
2334 * @attr: the invalid schema attribute
2335 * @message: the error message
2336 * @str1: the optional param for the error message
2337 *
2338 * Reports an attribute use error during parsing.
2339 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002340static void
2341xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002342 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002343 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002344 const xmlSchemaAttributePtr attr,
2345 const char *message,
2346 const xmlChar *str1)
2347{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002348 xmlChar *str = NULL, *msg = NULL;
2349 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2350 msg = xmlStrcat(msg, BAD_CAST ", ");
2351 msg = xmlStrcat(msg,
2352 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2353 (xmlSchemaTypePtr) attr, NULL));
2354 FREE_AND_NULL(str);
2355 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002356 msg = xmlStrcat(msg, (const xmlChar *) message);
2357 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002358 xmlSchemaPErr(ctxt, attr->node, error,
2359 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002360 xmlFree(msg);
2361}
2362
William M. Brack2f2a6632004-08-20 23:09:47 +00002363/**
2364 * xmlSchemaPIllegalFacetAtomicErr:
2365 * @ctxt: the schema parser context
2366 * @error: the error code
2367 * @itemDes: the designation of the type
2368 * @item: the schema type
2369 * @baseItem: the base type of type
2370 * @facet: the illegal facet
2371 *
2372 * Reports an illegal facet for atomic simple types.
2373 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002374static void
2375xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002376 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002377 xmlChar **itemDes,
2378 xmlSchemaTypePtr item,
2379 xmlSchemaTypePtr baseItem,
2380 xmlSchemaFacetPtr facet)
2381{
2382 xmlChar *des = NULL, *strT = NULL;
2383
2384 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2385 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2386 "%s: The facet '%s' is not allowed on types derived from the "
2387 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002388 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002389 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002390 NULL, NULL);
2391 if (itemDes == NULL)
2392 FREE_AND_NULL(des);
2393 FREE_AND_NULL(strT);
2394}
2395
William M. Brack2f2a6632004-08-20 23:09:47 +00002396/**
2397 * xmlSchemaPIllegalFacetListUnionErr:
2398 * @ctxt: the schema parser context
2399 * @error: the error code
2400 * @itemDes: the designation of the schema item involved
2401 * @item: the schema item involved
2402 * @facet: the illegal facet
2403 *
2404 * Reports an illegal facet for <list> and <union>.
2405 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002406static void
2407xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002408 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002409 xmlChar **itemDes,
2410 xmlSchemaTypePtr item,
2411 xmlSchemaFacetPtr facet)
2412{
2413 xmlChar *des = NULL, *strT = NULL;
2414
2415 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002416 xmlSchemaPErr(ctxt, item->node, error,
2417 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002418 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002419 if (itemDes == NULL)
2420 FREE_AND_NULL(des);
2421 FREE_AND_NULL(strT);
2422}
2423
2424/**
2425 * xmlSchemaPMutualExclAttrErr:
2426 * @ctxt: the schema validation context
2427 * @error: the error code
2428 * @elemDes: the designation of the parent element node
2429 * @attr: the bad attribute node
2430 * @type: the corresponding type of the attribute node
2431 *
2432 * Reports an illegal attribute.
2433 */
2434static void
2435xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2436 xmlParserErrors error,
2437 xmlChar **ownerDes,
2438 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002439 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002440 const char *name1,
2441 const char *name2)
2442{
2443 xmlChar *des = NULL;
2444
2445 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002446 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002447 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002448 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002449 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002450 } else
2451 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002452 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002453 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002454 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2455 if (ownerDes == NULL)
2456 FREE_AND_NULL(des)
2457}
2458
2459/**
2460 * xmlSchemaPSimpleTypeErr:
2461 * @ctxt: the schema validation context
2462 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002463 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002464 * @ownerDes: the designation of the owner
2465 * @ownerItem: the schema object if existent
2466 * @node: the validated node
2467 * @value: the validated value
2468 *
2469 * Reports a simple type validation error.
2470 * TODO: Should this report the value of an element as well?
2471 */
2472static void
2473xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2474 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002475 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002476 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002477 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002478 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002479 const xmlChar *value,
2480 const char *message,
2481 const xmlChar *str1,
2482 const xmlChar *str2)
2483{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002484 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002485
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002486 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002487 if (message == NULL) {
2488 /*
2489 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002490 */
2491 if (type != NULL) {
2492 if (node->type == XML_ATTRIBUTE_NODE)
2493 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2494 else
2495 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2496 "valid value of ");
2497 if (! xmlSchemaIsGlobalItem(type))
2498 msg = xmlStrcat(msg, BAD_CAST "the local ");
2499 else
2500 msg = xmlStrcat(msg, BAD_CAST "the ");
2501
2502 if (VARIETY_ATOMIC(type))
2503 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2504 else if (VARIETY_LIST(type))
2505 msg = xmlStrcat(msg, BAD_CAST "list type");
2506 else if (VARIETY_UNION(type))
2507 msg = xmlStrcat(msg, BAD_CAST "union type");
2508
2509 if (xmlSchemaIsGlobalItem(type)) {
2510 xmlChar *str = NULL;
2511 msg = xmlStrcat(msg, BAD_CAST " '");
2512 if (type->builtInType != 0) {
2513 msg = xmlStrcat(msg, BAD_CAST "xs:");
2514 msg = xmlStrcat(msg, type->name);
2515 } else
2516 msg = xmlStrcat(msg,
2517 xmlSchemaFormatQName(&str,
2518 type->targetNamespace, type->name));
2519 msg = xmlStrcat(msg, BAD_CAST "'.");
2520 FREE_AND_NULL(str);
2521 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002522 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002523 if (node->type == XML_ATTRIBUTE_NODE)
2524 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2525 else
2526 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2527 "valid.");
2528 }
2529 if (expected) {
2530 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2531 msg = xmlStrcat(msg, BAD_CAST expected);
2532 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2533 } else
2534 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002535 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002536 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2537 else
2538 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2539 } else {
2540 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
2541 "%s%s.\n", msg, BAD_CAST message, str1, str2, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002542 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002543 /* Cleanup. */
2544 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002545}
2546
William M. Brack2f2a6632004-08-20 23:09:47 +00002547/**
2548 * xmlSchemaPContentErr:
2549 * @ctxt: the schema parser context
2550 * @error: the error code
2551 * @onwerDes: the designation of the holder of the content
2552 * @ownerItem: the owner item of the holder of the content
2553 * @ownerElem: the node of the holder of the content
2554 * @child: the invalid child node
2555 * @message: the optional error message
2556 * @content: the optional string describing the correct content
2557 *
2558 * Reports an error concerning the content of a schema element.
2559 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002560static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002561xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002562 xmlParserErrors error,
2563 xmlChar **ownerDes,
2564 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002565 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002566 xmlNodePtr child,
2567 const char *message,
2568 const char *content)
2569{
2570 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002571
Daniel Veillardc0826a72004-08-10 14:17:33 +00002572 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002573 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002574 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002575 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002576 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002577 } else
2578 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002579 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002580 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2581 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002582 BAD_CAST des, BAD_CAST message);
2583 else {
2584 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002585 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2586 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002587 BAD_CAST des, BAD_CAST content);
2588 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002589 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2590 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002591 BAD_CAST des, NULL);
2592 }
2593 }
2594 if (ownerDes == NULL)
2595 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002596}
2597
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002598/************************************************************************
2599 * *
2600 * Streamable error functions *
2601 * *
2602 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002603
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002604
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002605
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002606
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002607/************************************************************************
2608 * *
2609 * Validation helper functions *
2610 * *
2611 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002612
Daniel Veillardc0826a72004-08-10 14:17:33 +00002613
Daniel Veillard4255d502002-04-16 15:50:10 +00002614/************************************************************************
2615 * *
2616 * Allocation functions *
2617 * *
2618 ************************************************************************/
2619
2620/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002621 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002622 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002623 *
2624 * Allocate a new Schema structure.
2625 *
2626 * Returns the newly allocated structure or NULL in case or error
2627 */
2628static xmlSchemaPtr
2629xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2630{
2631 xmlSchemaPtr ret;
2632
2633 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2634 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002635 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002636 return (NULL);
2637 }
2638 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002639 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002640 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002641
2642 return (ret);
2643}
2644
2645/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002646 * xmlSchemaNewSchema:
2647 * @ctxt: a schema validation context
2648 *
2649 * Allocate a new Schema structure.
2650 *
2651 * Returns the newly allocated structure or NULL in case or error
2652 */
2653static xmlSchemaAssemblePtr
2654xmlSchemaNewAssemble(void)
2655{
2656 xmlSchemaAssemblePtr ret;
2657
2658 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2659 if (ret == NULL) {
2660 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2661 return (NULL);
2662 }
2663 memset(ret, 0, sizeof(xmlSchemaAssemble));
2664 ret->items = NULL;
2665 return (ret);
2666}
2667
2668/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002669 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002670 *
2671 * Allocate a new Facet structure.
2672 *
2673 * Returns the newly allocated structure or NULL in case or error
2674 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002675xmlSchemaFacetPtr
2676xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002677{
2678 xmlSchemaFacetPtr ret;
2679
2680 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2681 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002682 return (NULL);
2683 }
2684 memset(ret, 0, sizeof(xmlSchemaFacet));
2685
2686 return (ret);
2687}
2688
2689/**
2690 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002691 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002692 * @node: a node
2693 *
2694 * Allocate a new annotation structure.
2695 *
2696 * Returns the newly allocated structure or NULL in case or error
2697 */
2698static xmlSchemaAnnotPtr
2699xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2700{
2701 xmlSchemaAnnotPtr ret;
2702
2703 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2704 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002705 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002706 return (NULL);
2707 }
2708 memset(ret, 0, sizeof(xmlSchemaAnnot));
2709 ret->content = node;
2710 return (ret);
2711}
2712
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002713static xmlSchemaItemListPtr
2714xmlSchemaNewItemList(void)
2715{
2716 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002717
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002718 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2719 if (ret == NULL) {
2720 xmlSchemaPErrMemory(NULL,
2721 "allocating an item list structure", NULL);
2722 return (NULL);
2723 }
2724 memset(ret, 0, sizeof(xmlSchemaItemList));
2725 return (ret);
2726}
2727
2728/**
2729 * xmlSchemaAddElementSubstitutionMember:
2730 * @pctxt: a schema parser context
2731 * @head: the head of the substitution group
2732 * @member: the new member of the substitution group
2733 *
2734 * Allocate a new annotation structure.
2735 *
2736 * Returns the newly allocated structure or NULL in case or error
2737 */
2738static int
2739xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
2740 xmlSchemaElementPtr head,
2741 xmlSchemaElementPtr member)
2742{
2743 xmlSchemaSubstGroupPtr substGroup;
2744
2745 if (pctxt == NULL)
2746 return (-1);
2747
2748 if (pctxt->substGroups == NULL) {
2749 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
2750 if (pctxt->substGroups == NULL)
2751 return (-1);
2752 }
2753 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
2754 head->targetNamespace);
2755 if (substGroup == NULL) {
2756 int res;
2757
2758 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
2759 if (substGroup == NULL) {
2760 xmlSchemaPErrMemory(NULL,
2761 "xmlSchemaAddElementSubstitution, allocating a substitution "
2762 "group container",
2763 NULL);
2764 return (-1);
2765 }
2766 substGroup->members = xmlSchemaNewItemList();
2767 if (substGroup->members == NULL) {
2768 xmlFree(substGroup);
2769 return (-1);
2770 }
2771 substGroup->head = head;
2772
2773 res = xmlHashAddEntry2(pctxt->substGroups,
2774 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002775 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002776 xmlFree(substGroup->members);
2777 xmlFree(substGroup);
2778 xmlSchemaPErr(pctxt, member->node,
2779 XML_SCHEMAP_INTERNAL,
2780 "Internal error: xmlSchemaAddElementSubstitution, "
2781 "failed to add a new substitution group container for "
2782 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002783 return (-1);
2784 }
2785 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002786 if (substGroup->members->items == NULL) {
2787 substGroup->members->items = (void **) xmlMalloc(
2788 5 * sizeof(xmlSchemaElementPtr));
2789 if (substGroup->members->items == NULL) {
2790 xmlSchemaPErrMemory(NULL,
2791 "allocating list of substitution group members", NULL);
2792 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002793 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002794 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002795 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002796 substGroup->members->nbItems) {
2797 substGroup->members->sizeItems *= 2;
2798 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002799 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002800 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
2801 if (substGroup->members->items == NULL) {
2802 xmlSchemaPErrMemory(NULL,
2803 "re-allocating list of substitution group members", NULL);
2804 substGroup->members->sizeItems = 0;
2805 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002806 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002807 }
2808 ((xmlSchemaElementPtr *) substGroup->members->items)
2809 [substGroup->members->nbItems++] = (void *) member;
2810 return (0);
2811}
2812
2813/**
2814 * xmlSchemaGetElementSubstitutionGroup:
2815 * @pctxt: a schema parser context
2816 * @head: the head of the substitution group
2817 * @member: the new member of the substitution group
2818 *
2819 * Allocate a new annotation structure.
2820 *
2821 * Returns the newly allocated structure or NULL in case or error
2822 */
2823static xmlSchemaSubstGroupPtr
2824xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
2825 xmlSchemaElementPtr head)
2826{
2827 if (pctxt == NULL)
2828 return (NULL);
2829
2830 if (pctxt->substGroups == NULL)
2831 return (NULL);
2832
2833 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
2834 head->name, head->targetNamespace));
2835}
2836
2837/**
2838 * xmlSchemaFreeItemList:
2839 * @annot: a schema type structure
2840 *
2841 * Deallocate a annotation structure
2842 */
2843static void
2844xmlSchemaFreeItemList(xmlSchemaItemListPtr list)
2845{
2846 if (list == NULL)
2847 return;
2848 if (list->items != NULL)
2849 xmlFree(list->items);
2850 xmlFree(list);
2851}
2852
Daniel Veillard4255d502002-04-16 15:50:10 +00002853/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002854 * xmlSchemaFreeAnnot:
2855 * @annot: a schema type structure
2856 *
2857 * Deallocate a annotation structure
2858 */
2859static void
2860xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2861{
2862 if (annot == NULL)
2863 return;
2864 xmlFree(annot);
2865}
2866
2867/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002868 * xmlSchemaFreeImport:
2869 * @import: a schema import structure
2870 *
2871 * Deallocate an import structure
2872 */
2873static void
2874xmlSchemaFreeImport(xmlSchemaImportPtr import)
2875{
2876 if (import == NULL)
2877 return;
2878
2879 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002880 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002881 xmlFree(import);
2882}
2883
2884/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002885 * xmlSchemaFreeInclude:
2886 * @include: a schema include structure
2887 *
2888 * Deallocate an include structure
2889 */
2890static void
2891xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2892{
2893 if (include == NULL)
2894 return;
2895
2896 xmlFreeDoc(include->doc);
2897 xmlFree(include);
2898}
2899
2900/**
2901 * xmlSchemaFreeIncludeList:
2902 * @includes: a schema include list
2903 *
2904 * Deallocate an include structure
2905 */
2906static void
2907xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2908{
2909 xmlSchemaIncludePtr next;
2910
2911 while (includes != NULL) {
2912 next = includes->next;
2913 xmlSchemaFreeInclude(includes);
2914 includes = next;
2915 }
2916}
2917
2918/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002919 * xmlSchemaFreeNotation:
2920 * @schema: a schema notation structure
2921 *
2922 * Deallocate a Schema Notation structure.
2923 */
2924static void
2925xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2926{
2927 if (nota == NULL)
2928 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002929 xmlFree(nota);
2930}
2931
2932/**
2933 * xmlSchemaFreeAttribute:
2934 * @schema: a schema attribute structure
2935 *
2936 * Deallocate a Schema Attribute structure.
2937 */
2938static void
2939xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2940{
2941 if (attr == NULL)
2942 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002943 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002944 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002945 if (attr->defVal != NULL)
2946 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002947 xmlFree(attr);
2948}
2949
2950/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002951 * xmlSchemaFreeWildcardNsSet:
2952 * set: a schema wildcard namespace
2953 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002954 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002955 */
2956static void
2957xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2958{
2959 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002960
Daniel Veillard3646d642004-06-02 19:19:14 +00002961 while (set != NULL) {
2962 next = set->next;
2963 xmlFree(set);
2964 set = next;
2965 }
2966}
2967
2968/**
2969 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002970 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002971 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002972 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002973 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002974void
Daniel Veillard3646d642004-06-02 19:19:14 +00002975xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2976{
2977 if (wildcard == NULL)
2978 return;
2979 if (wildcard->annot != NULL)
2980 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002981 if (wildcard->nsSet != NULL)
2982 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2983 if (wildcard->negNsSet != NULL)
2984 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00002985 xmlFree(wildcard);
2986}
2987
2988/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002989 * xmlSchemaFreeAttributeGroup:
2990 * @schema: a schema attribute group structure
2991 *
2992 * Deallocate a Schema Attribute Group structure.
2993 */
2994static void
2995xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2996{
2997 if (attr == NULL)
2998 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002999 if (attr->annot != NULL)
3000 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003001 xmlFree(attr);
3002}
3003
3004/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003005 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003006 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003007 *
3008 * Deallocate a list of schema attribute uses.
3009 */
3010static void
3011xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3012{
3013 xmlSchemaAttributeLinkPtr next;
3014
3015 while (attrUse != NULL) {
3016 next = attrUse->next;
3017 xmlFree(attrUse);
3018 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003019 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003020}
3021
3022/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003023 * xmlSchemaFreeQNameRef:
3024 * @item: a QName reference structure
3025 *
3026 * Deallocatea a QName reference structure.
3027 */
3028static void
3029xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3030{
3031 xmlFree(item);
3032}
3033
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003034/**
3035 * xmlSchemaFreeQNameRef:
3036 * @item: a QName reference structure
3037 *
3038 * Deallocatea a QName reference structure.
3039 */
3040static void
3041xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3042{
3043 if (item == NULL)
3044 return;
3045 if (item->members != NULL)
3046 xmlSchemaFreeItemList(item->members);
3047 xmlFree(item);
3048}
3049
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003050static int
3051xmlSchemaAddVolatile(xmlSchemaPtr schema,
3052 xmlSchemaBasicItemPtr item)
3053{
3054 xmlSchemaItemListPtr list;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003055
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003056 if (schema->volatiles == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003057 schema->volatiles = (void *) xmlSchemaNewItemList();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003058 if (schema->volatiles == NULL) {
3059 xmlSchemaPErrMemory(NULL,
3060 "allocating list of volatiles", NULL);
3061 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003062 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003063 }
3064 list = (xmlSchemaItemListPtr) schema->volatiles;
3065 if (list->items == NULL) {
3066 list->items = (void **) xmlMalloc(
3067 20 * sizeof(xmlSchemaBasicItemPtr));
3068 if (list->items == NULL) {
3069 xmlSchemaPErrMemory(NULL,
3070 "allocating new volatile item buffer", NULL);
3071 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003072 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003073 list->sizeItems = 20;
3074 } else if (list->sizeItems <= list->nbItems) {
3075 list->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003076 list->items = (void **) xmlRealloc(list->items,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003077 list->sizeItems * sizeof(xmlSchemaTypePtr));
3078 if (list->items == NULL) {
3079 xmlSchemaPErrMemory(NULL,
3080 "growing volatile item buffer", NULL);
3081 list->sizeItems = 0;
3082 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003083 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003084 }
3085 ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item;
3086 return (0);
3087}
3088
3089/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003090 * xmlSchemaFreeTypeLinkList:
3091 * @alink: a type link
3092 *
3093 * Deallocate a list of types.
3094 */
3095static void
3096xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3097{
3098 xmlSchemaTypeLinkPtr next;
3099
3100 while (link != NULL) {
3101 next = link->next;
3102 xmlFree(link);
3103 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003104 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003105}
3106
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003107static void
3108xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3109{
3110 xmlSchemaIDCStateObjPtr next;
3111 while (sto != NULL) {
3112 next = sto->next;
3113 if (sto->history != NULL)
3114 xmlFree(sto->history);
3115 if (sto->xpathCtxt != NULL)
3116 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3117 xmlFree(sto);
3118 sto = next;
3119 }
3120}
3121
3122/**
3123 * xmlSchemaFreeIDC:
3124 * @idc: a identity-constraint definition
3125 *
3126 * Deallocates an identity-constraint definition.
3127 */
3128static void
3129xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3130{
3131 xmlSchemaIDCSelectPtr cur, prev;
3132
3133 if (idcDef == NULL)
3134 return;
3135 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003136 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003137 /* Selector */
3138 if (idcDef->selector != NULL) {
3139 if (idcDef->selector->xpathComp != NULL)
3140 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3141 xmlFree(idcDef->selector);
3142 }
3143 /* Fields */
3144 if (idcDef->fields != NULL) {
3145 cur = idcDef->fields;
3146 do {
3147 prev = cur;
3148 cur = cur->next;
3149 if (prev->xpathComp != NULL)
3150 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003151 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003152 } while (cur != NULL);
3153 }
3154 xmlFree(idcDef);
3155}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003156
Daniel Veillard01fa6152004-06-29 17:04:39 +00003157/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003158 * xmlSchemaFreeElement:
3159 * @schema: a schema element structure
3160 *
3161 * Deallocate a Schema Element structure.
3162 */
3163static void
3164xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3165{
3166 if (elem == NULL)
3167 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003168 if (elem->annot != NULL)
3169 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003170 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003171 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003172 if (elem->defVal != NULL)
3173 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003174 xmlFree(elem);
3175}
3176
3177/**
3178 * xmlSchemaFreeFacet:
3179 * @facet: a schema facet structure
3180 *
3181 * Deallocate a Schema Facet structure.
3182 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003183void
Daniel Veillard4255d502002-04-16 15:50:10 +00003184xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3185{
3186 if (facet == NULL)
3187 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003188 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003189 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003190 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003191 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003192 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003193 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003194 xmlFree(facet);
3195}
3196
3197/**
3198 * xmlSchemaFreeType:
3199 * @type: a schema type structure
3200 *
3201 * Deallocate a Schema Type structure.
3202 */
3203void
3204xmlSchemaFreeType(xmlSchemaTypePtr type)
3205{
3206 if (type == NULL)
3207 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003208 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003209 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003210 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003211 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003212
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003213 facet = type->facets;
3214 while (facet != NULL) {
3215 next = facet->next;
3216 xmlSchemaFreeFacet(facet);
3217 facet = next;
3218 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003219 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003220 if (type->type != XML_SCHEMA_TYPE_BASIC) {
3221 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003222 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003223 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003224 if (type->memberTypes != NULL)
3225 xmlSchemaFreeTypeLinkList(type->memberTypes);
3226 if (type->facetSet != NULL) {
3227 xmlSchemaFacetLinkPtr next, link;
3228
3229 link = type->facetSet;
3230 do {
3231 next = link->next;
3232 xmlFree(link);
3233 link = next;
3234 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003235 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003236 if (type->contModel != NULL)
3237 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003238 xmlFree(type);
3239}
3240
3241/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003242 * xmlSchemaFreeModelGroupDef:
3243 * @item: a schema model group definition
3244 *
3245 * Deallocates a schema model group definition.
3246 */
3247static void
3248xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3249{
3250 if (item->annot != NULL)
3251 xmlSchemaFreeAnnot(item->annot);
3252 xmlFree(item);
3253}
3254
3255/**
3256 * xmlSchemaFreeModelGroup:
3257 * @item: a schema model group
3258 *
3259 * Deallocates a schema model group structure.
3260 */
3261static void
3262xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3263{
3264 if (item->annot != NULL)
3265 xmlSchemaFreeAnnot(item->annot);
3266 xmlFree(item);
3267}
3268
3269/**
3270 * xmlSchemaFreeParticle:
3271 * @type: a schema type structure
3272 *
3273 * Deallocate a Schema Type structure.
3274 */
3275static void
3276xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3277{
3278 if (item->annot != NULL)
3279 xmlSchemaFreeAnnot(item->annot);
3280 xmlFree(item);
3281}
3282
3283/**
3284 * xmlSchemaFreeMiscComponents:
3285 * @item: a schema component
3286 *
3287 * Deallocates misc. schema component structures.
3288 */
3289static void
3290xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3291{
3292 if (item == NULL)
3293 return;
3294 switch (item->type) {
3295 case XML_SCHEMA_TYPE_PARTICLE:
3296 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3297 return;
3298 case XML_SCHEMA_TYPE_SEQUENCE:
3299 case XML_SCHEMA_TYPE_CHOICE:
3300 case XML_SCHEMA_TYPE_ALL:
3301 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3302 return;
3303 case XML_SCHEMA_TYPE_ANY:
3304 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3305 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3306 break;
3307 default:
3308 /* TODO: This should never be hit. */
3309 TODO
3310 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003311 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003312}
3313
3314static void
3315xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3316{
3317 if (schema->volatiles == NULL)
3318 return;
3319 {
3320 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3321 xmlSchemaTreeItemPtr item;
3322 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003323
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003324 for (i = 0; i < list->nbItems; i++) {
3325 if (list->items[i] != NULL) {
3326 item = (xmlSchemaTreeItemPtr) list->items[i];
3327 switch (item->type) {
3328 case XML_SCHEMA_EXTRA_QNAMEREF:
3329 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3330 break;
3331 default:
3332 xmlSchemaFreeMiscComponents(item);
3333 }
3334 }
3335 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003336 xmlSchemaFreeItemList(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003337 }
3338}
3339/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003340 * xmlSchemaFreeTypeList:
3341 * @type: a schema type structure
3342 *
3343 * Deallocate a Schema Type structure.
3344 */
3345static void
3346xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3347{
3348 xmlSchemaTypePtr next;
3349
3350 while (type != NULL) {
3351 next = type->redef;
3352 xmlSchemaFreeType(type);
3353 type = next;
3354 }
3355}
3356
3357/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003358 * xmlSchemaFree:
3359 * @schema: a schema structure
3360 *
3361 * Deallocate a Schema structure.
3362 */
3363void
3364xmlSchemaFree(xmlSchemaPtr schema)
3365{
3366 if (schema == NULL)
3367 return;
3368
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003369 if (schema->volatiles != NULL)
3370 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003371 if (schema->notaDecl != NULL)
3372 xmlHashFree(schema->notaDecl,
3373 (xmlHashDeallocator) xmlSchemaFreeNotation);
3374 if (schema->attrDecl != NULL)
3375 xmlHashFree(schema->attrDecl,
3376 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3377 if (schema->attrgrpDecl != NULL)
3378 xmlHashFree(schema->attrgrpDecl,
3379 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3380 if (schema->elemDecl != NULL)
3381 xmlHashFree(schema->elemDecl,
3382 (xmlHashDeallocator) xmlSchemaFreeElement);
3383 if (schema->typeDecl != NULL)
3384 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003385 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003386 if (schema->groupDecl != NULL)
3387 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003388 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003389 if (schema->idcDef != NULL)
3390 xmlHashFree(schema->idcDef,
3391 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003392 if (schema->schemasImports != NULL)
3393 xmlHashFree(schema->schemasImports,
3394 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003395 if (schema->includes != NULL) {
3396 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3397 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003398 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003399 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003400 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003401 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003402 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003403 xmlFree(schema);
3404}
3405
3406/************************************************************************
3407 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003408 * Debug functions *
3409 * *
3410 ************************************************************************/
3411
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003412#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003413
Daniel Veillard4255d502002-04-16 15:50:10 +00003414/**
3415 * xmlSchemaElementDump:
3416 * @elem: an element
3417 * @output: the file output
3418 *
3419 * Dump the element
3420 */
3421static void
3422xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003423 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003424 const xmlChar * namespace ATTRIBUTE_UNUSED,
3425 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003426{
3427 if (elem == NULL)
3428 return;
3429
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003430 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3431 fprintf(output, "Particle: %s", name);
3432 fprintf(output, ", term element: %s", elem->ref);
3433 if (elem->refNs != NULL)
3434 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003435 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003436 fprintf(output, "Element");
3437 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3438 fprintf(output, " (global)");
3439 fprintf(output, ": %s ", elem->name);
3440 if (namespace != NULL)
3441 fprintf(output, "ns %s", namespace);
3442 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003443 fprintf(output, "\n");
3444 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003445 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003446 if (elem->maxOccurs >= UNBOUNDED)
3447 fprintf(output, "max: unbounded\n");
3448 else if (elem->maxOccurs != 1)
3449 fprintf(output, "max: %d\n", elem->maxOccurs);
3450 else
3451 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003452 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003453 /*
3454 * Misc other properties.
3455 */
3456 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3457 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3458 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3459 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3460 (elem->id != NULL)) {
3461 fprintf(output, " props: ");
3462 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3463 fprintf(output, "[fixed] ");
3464 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3465 fprintf(output, "[default] ");
3466 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3467 fprintf(output, "[abstract] ");
3468 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3469 fprintf(output, "[nillable] ");
3470 if (elem->id != NULL)
3471 fprintf(output, "[id: '%s'] ", elem->id);
3472 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003473 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003474 /*
3475 * Default/fixed value.
3476 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003477 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003478 fprintf(output, " value: '%s'\n", elem->value);
3479 /*
3480 * Type.
3481 */
3482 if (elem->namedType != NULL) {
3483 fprintf(output, " type: %s ", elem->namedType);
3484 if (elem->namedTypeNs != NULL)
3485 fprintf(output, "ns %s\n", elem->namedTypeNs);
3486 else
3487 fprintf(output, "\n");
3488 }
3489 /*
3490 * Substitution group.
3491 */
3492 if (elem->substGroup != NULL) {
3493 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3494 if (elem->substGroupNs != NULL)
3495 fprintf(output, "ns %s\n", elem->substGroupNs);
3496 else
3497 fprintf(output, "\n");
3498 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003499}
3500
3501/**
3502 * xmlSchemaAnnotDump:
3503 * @output: the file output
3504 * @annot: a annotation
3505 *
3506 * Dump the annotation
3507 */
3508static void
3509xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3510{
3511 xmlChar *content;
3512
3513 if (annot == NULL)
3514 return;
3515
3516 content = xmlNodeGetContent(annot->content);
3517 if (content != NULL) {
3518 fprintf(output, " Annot: %s\n", content);
3519 xmlFree(content);
3520 } else
3521 fprintf(output, " Annot: empty\n");
3522}
3523
3524/**
3525 * xmlSchemaTypeDump:
3526 * @output: the file output
3527 * @type: a type structure
3528 *
3529 * Dump a SchemaType structure
3530 */
3531static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003532xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3533{
3534 xmlChar *str = NULL;
3535 xmlSchemaTreeItemPtr term;
3536 char shift[100];
3537 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003538
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003539 if (particle == NULL)
3540 return;
3541 for (i = 0;((i < depth) && (i < 25));i++)
3542 shift[2 * i] = shift[2 * i + 1] = ' ';
3543 shift[2 * i] = shift[2 * i + 1] = 0;
3544 fprintf(output, shift);
3545 if (particle->children == NULL) {
3546 fprintf(output, "MISSING particle term\n");
3547 return;
3548 }
3549 term = particle->children;
3550 switch (term->type) {
3551 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003552 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003553 ((xmlSchemaElementPtr)term)->targetNamespace,
3554 ((xmlSchemaElementPtr)term)->name));
3555 break;
3556 case XML_SCHEMA_TYPE_SEQUENCE:
3557 fprintf(output, "SEQUENCE");
3558 break;
3559 case XML_SCHEMA_TYPE_CHOICE:
3560 fprintf(output, "CHOICE");
3561 break;
3562 case XML_SCHEMA_TYPE_ALL:
3563 fprintf(output, "ALL");
3564 break;
3565 case XML_SCHEMA_TYPE_ANY:
3566 fprintf(output, "ANY");
3567 break;
3568 default:
3569 fprintf(output, "UNKNOWN\n");
3570 return;
3571 }
3572 if (particle->minOccurs != 1)
3573 fprintf(output, " min: %d", particle->minOccurs);
3574 if (particle->maxOccurs >= UNBOUNDED)
3575 fprintf(output, " max: unbounded");
3576 else if (particle->maxOccurs != 1)
3577 fprintf(output, " max: %d", particle->maxOccurs);
3578 fprintf(output, "\n");
3579 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3580 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3581 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3582 (term->children != NULL)) {
3583 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3584 output, depth +1);
3585 }
3586 if (particle->next != NULL)
3587 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3588 output, depth);
3589}
3590/**
3591 * xmlSchemaTypeDump:
3592 * @output: the file output
3593 * @type: a type structure
3594 *
3595 * Dump a SchemaType structure
3596 */
3597static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003598xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3599{
3600 if (type == NULL) {
3601 fprintf(output, "Type: NULL\n");
3602 return;
3603 }
3604 fprintf(output, "Type: ");
3605 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003606 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003607 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003608 fprintf(output, "no name ");
3609 if (type->targetNamespace != NULL)
3610 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003611 switch (type->type) {
3612 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003613 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003614 break;
3615 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003616 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003617 break;
3618 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003619 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003620 break;
3621 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003622 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 break;
3624 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003625 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003626 break;
3627 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003628 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 break;
3630 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003631 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003632 break;
3633 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003634 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003635 break;
3636 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003637 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003638 break;
3639 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003640 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003641 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003642 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003643 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003644 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003645 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003646 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003647 break;
3648 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003649 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003650 break;
3651 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003652 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003653 break;
3654 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003655 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003656 break;
3657 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003658 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003659 break;
3660 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003661 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003662 break;
3663 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003664 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003665 break;
3666 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003667 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003668 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003669 }
3670 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003671 if (type->base != NULL) {
3672 fprintf(output, " base type: %s", type->base);
3673 if (type->baseNs != NULL)
3674 fprintf(output, " ns %s\n", type->baseNs);
3675 else
3676 fprintf(output, "\n");
3677 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003678 if (type->annot != NULL)
3679 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003680#ifdef DUMP_CONTENT_MODEL
3681 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3682 (type->subtypes != NULL)) {
3683 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3684 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003686#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003687}
3688
3689/**
3690 * xmlSchemaDump:
3691 * @output: the file output
3692 * @schema: a schema structure
3693 *
3694 * Dump a Schema structure.
3695 */
3696void
3697xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3698{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003699 if (output == NULL)
3700 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003701 if (schema == NULL) {
3702 fprintf(output, "Schemas: NULL\n");
3703 return;
3704 }
3705 fprintf(output, "Schemas: ");
3706 if (schema->name != NULL)
3707 fprintf(output, "%s, ", schema->name);
3708 else
3709 fprintf(output, "no name, ");
3710 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003711 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003712 else
3713 fprintf(output, "no target namespace");
3714 fprintf(output, "\n");
3715 if (schema->annot != NULL)
3716 xmlSchemaAnnotDump(output, schema->annot);
3717
3718 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3719 output);
3720 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003721 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003722}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003723
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003724#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003725/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003726 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003727 * @vctxt: the WXS validation context
3728 *
3729 * Displays the current IDC table for debug purposes.
3730 */
3731static void
3732xmlSchemaDebugDumpIDCTable(FILE * output,
3733 const xmlChar *namespaceName,
3734 const xmlChar *localName,
3735 xmlSchemaPSVIIDCBindingPtr bind)
3736{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003737 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003738 xmlSchemaPSVIIDCNodePtr tab;
3739 xmlSchemaPSVIIDCKeyPtr key;
3740 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003741
3742 fprintf(output, "IDC: TABLES on %s\n",
3743 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003744 FREE_AND_NULL(str)
3745
3746 if (bind == NULL)
3747 return;
3748 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003749 fprintf(output, "IDC: BINDING %s\n",
3750 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003751 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003752 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003753 for (i = 0; i < bind->nbNodes; i++) {
3754 tab = bind->nodeTable[i];
3755 fprintf(output, " ( ");
3756 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003757 key = tab->keys[j];
3758 if ((key != NULL) && (key->val != NULL)) {
3759 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003760 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003761 fprintf(output, "\"%s\" ", value);
3762 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003763 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003764 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003765 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003766 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003767 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003768 else
3769 fprintf(output, "(key missing), ");
3770 }
3771 fprintf(output, ")\n");
3772 }
3773 bind = bind->next;
3774 } while (bind != NULL);
3775}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003776#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003777#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00003778
3779/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003780 * *
3781 * Utilities *
3782 * *
3783 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003784
Daniel Veillardc0826a72004-08-10 14:17:33 +00003785/**
3786 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003787 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003788 * @name: the name of the attribute
3789 *
3790 * Seeks an attribute with a name of @name in
3791 * no namespace.
3792 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003793 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003794 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003795static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003796xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003797{
3798 xmlAttrPtr prop;
3799
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003800 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003801 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003802 prop = node->properties;
3803 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003804 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003805 return(prop);
3806 prop = prop->next;
3807 }
3808 return (NULL);
3809}
3810
3811/**
3812 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003813 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00003814 * @uri: the uri
3815 * @name: the name of the attribute
3816 *
3817 * Seeks an attribute with a local name of @name and
3818 * a namespace URI of @uri.
3819 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003820 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00003821 */
3822static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003823xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003824{
3825 xmlAttrPtr prop;
3826
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003827 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00003828 return(NULL);
3829 prop = node->properties;
3830 while (prop != NULL) {
3831 if ((prop->ns != NULL) &&
3832 xmlStrEqual(prop->name, BAD_CAST name) &&
3833 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003834 return(prop);
3835 prop = prop->next;
3836 }
3837 return (NULL);
3838}
3839
3840static const xmlChar *
3841xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3842{
3843 xmlChar *val;
3844 const xmlChar *ret;
3845
3846 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003847 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00003848 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00003849 ret = xmlDictLookup(ctxt->dict, val, -1);
3850 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003851 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003852}
3853
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003854/**
3855 * xmlSchemaGetProp:
3856 * @ctxt: the parser context
3857 * @node: the node
3858 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003859 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003860 * Read a attribute value and internalize the string
3861 *
3862 * Returns the string or NULL if not present.
3863 */
3864static const xmlChar *
3865xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3866 const char *name)
3867{
3868 xmlChar *val;
3869 const xmlChar *ret;
3870
3871 val = xmlGetProp(node, BAD_CAST name);
3872 if (val == NULL)
3873 return(NULL);
3874 ret = xmlDictLookup(ctxt->dict, val, -1);
3875 xmlFree(val);
3876 return(ret);
3877}
3878
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003879/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003880 * *
3881 * Parsing functions *
3882 * *
3883 ************************************************************************/
3884
3885/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003886 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003887 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003888 * @name: the element name
3889 * @ns: the element namespace
3890 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003891 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003892 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003893 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003894 */
3895static xmlSchemaElementPtr
3896xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003897 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003898{
3899 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003900
3901 if ((name == NULL) || (schema == NULL))
3902 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003903
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003904 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003905 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003906 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003907 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003908 } else
3909 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003910 /*
3911 * This one was removed, since top level element declarations have
3912 * the target namespace specified in targetNamespace of the <schema>
3913 * information element, even if elementFormDefault is "unqualified".
3914 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003915
William M. Bracke7091952004-05-11 15:09:58 +00003916 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003917 if (xmlStrEqual(namespace, schema->targetNamespace))
3918 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3919 else
3920 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003921 if ((ret != NULL) &&
3922 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003923 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003924 }
William M. Bracke7091952004-05-11 15:09:58 +00003925 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003926
William M. Brack2f2a6632004-08-20 23:09:47 +00003927 /*
3928 * Removed since imported components will be hold by the main schema only.
3929 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003930 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003931 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003932 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003933 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003934 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003935 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003936 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3937 return (ret);
3938 } else
3939 ret = NULL;
3940 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003941 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003942#ifdef DEBUG
3943 if (ret == NULL) {
3944 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003945 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003946 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003947 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003948 namespace);
3949 }
3950#endif
3951 return (ret);
3952}
3953
3954/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003955 * xmlSchemaGetType:
3956 * @schema: the schemas context
3957 * @name: the type name
3958 * @ns: the type namespace
3959 *
3960 * Lookup a type in the schemas or the predefined types
3961 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003962 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003963 */
3964static xmlSchemaTypePtr
3965xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003966 const xmlChar * namespace)
3967{
Daniel Veillard4255d502002-04-16 15:50:10 +00003968 xmlSchemaTypePtr ret;
3969
3970 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003971 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003972 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003973 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003974 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003975 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003976 }
3977 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003978 if (ret != NULL)
3979 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003980 /*
3981 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003982 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003983 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003984 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003985 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003986 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003987 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003988 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003989 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3990 return (ret);
3991 } else
3992 ret = NULL;
3993 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003994 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003995#ifdef DEBUG
3996 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003997 if (namespace == NULL)
3998 fprintf(stderr, "Unable to lookup type %s", name);
3999 else
4000 fprintf(stderr, "Unable to lookup type %s:%s", name,
4001 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00004002 }
4003#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004004 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004005}
4006
Daniel Veillard3646d642004-06-02 19:19:14 +00004007/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004008 * xmlSchemaGetAttributeDecl:
4009 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004010 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004011 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004012 *
4013 * Lookup a an attribute in the schema or imported schemas
4014 *
4015 * Returns the attribute declaration or NULL if not found.
4016 */
4017static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004018xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004019 const xmlChar * namespace)
4020{
4021 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004022
4023 if ((name == NULL) || (schema == NULL))
4024 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004025
4026
Daniel Veillard3646d642004-06-02 19:19:14 +00004027 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4028 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004029 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004030 else
4031 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004032 /*
4033 * Removed, since imported components will be hold by the main schema only.
4034 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004035 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004036 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004037 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004038 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004039 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004040 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004041 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4042 return (ret);
4043 } else
4044 ret = NULL;
4045 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004046 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004047#ifdef DEBUG
4048 if (ret == NULL) {
4049 if (namespace == NULL)
4050 fprintf(stderr, "Unable to lookup attribute %s", name);
4051 else
4052 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4053 namespace);
4054 }
4055#endif
4056 return (ret);
4057}
4058
4059/**
4060 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004061 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004062 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004063 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004064 *
4065 * Lookup a an attribute group in the schema or imported schemas
4066 *
4067 * Returns the attribute group definition or NULL if not found.
4068 */
4069static xmlSchemaAttributeGroupPtr
4070xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4071 const xmlChar * namespace)
4072{
4073 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004074
4075 if ((name == NULL) || (schema == NULL))
4076 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004077
4078
Daniel Veillard3646d642004-06-02 19:19:14 +00004079 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4080 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004081 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004082 else
4083 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004084 /*
4085 * Removed since imported components will be hold by the main schema only.
4086 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004087 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004088 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004089 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004090 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004091 if (import != NULL) {
4092 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4093 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4094 return (ret);
4095 else
4096 ret = NULL;
4097 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004098 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004099#ifdef DEBUG
4100 if (ret == NULL) {
4101 if (namespace == NULL)
4102 fprintf(stderr, "Unable to lookup attribute group %s", name);
4103 else
4104 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4105 namespace);
4106 }
4107#endif
4108 return (ret);
4109}
4110
4111/**
4112 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004113 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004114 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004115 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004116 *
4117 * Lookup a group in the schema or imported schemas
4118 *
4119 * Returns the group definition or NULL if not found.
4120 */
4121static xmlSchemaTypePtr
4122xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4123 const xmlChar * namespace)
4124{
4125 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004126
4127 if ((name == NULL) || (schema == NULL))
4128 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004129
Daniel Veillard3646d642004-06-02 19:19:14 +00004130 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004131 /*
4132 * Removed since imported components will be hold by the main schema only.
4133 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004134 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004135 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004136 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004137 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004138 if (import != NULL) {
4139 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4140 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4141 return (ret);
4142 else
4143 ret = NULL;
4144 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004145 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004146#ifdef DEBUG
4147 if (ret == NULL) {
4148 if (namespace == NULL)
4149 fprintf(stderr, "Unable to lookup group %s", name);
4150 else
4151 fprintf(stderr, "Unable to lookup group %s:%s", name,
4152 namespace);
4153 }
4154#endif
4155 return (ret);
4156}
4157
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004158/**
4159 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004160 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004161 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004162 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004163 *
4164 * Lookup a group in the schema or imported schemas
4165 *
4166 * Returns the group definition or NULL if not found.
4167 */
4168static xmlSchemaTreeItemPtr
4169xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4170 xmlSchemaTypeType itemType,
4171 const xmlChar *name,
4172 const xmlChar *targetNs)
4173{
4174 switch (itemType) {
4175 case XML_SCHEMA_TYPE_GROUP:
4176 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4177 name, targetNs));
4178 case XML_SCHEMA_TYPE_ELEMENT:
4179 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4180 name, targetNs));
4181 default:
4182 return (NULL);
4183 }
4184}
4185
Daniel Veillard4255d502002-04-16 15:50:10 +00004186/************************************************************************
4187 * *
4188 * Parsing functions *
4189 * *
4190 ************************************************************************/
4191
4192#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004193 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004194
4195/**
4196 * xmlSchemaIsBlank:
4197 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004198 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004199 *
4200 * Check if a string is ignorable
4201 *
4202 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4203 */
4204static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004205xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004206{
Daniel Veillard4255d502002-04-16 15:50:10 +00004207 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004208 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004209 if (len < 0) {
4210 while (*str != 0) {
4211 if (!(IS_BLANK_CH(*str)))
4212 return (0);
4213 str++;
4214 }
4215 } else while ((*str != 0) && (len != 0)) {
4216 if (!(IS_BLANK_CH(*str)))
4217 return (0);
4218 str++;
4219 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004220 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004221
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004222 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004223}
4224
4225/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004226 * xmlSchemaAddAssembledItem:
4227 * @ctxt: a schema parser context
4228 * @schema: the schema being built
4229 * @item: the item
4230 *
4231 * Add a item to the schema's list of current items.
4232 * This is used if the schema was already constructed and
4233 * new schemata need to be added to it.
4234 * *WARNING* this interface is highly subject to change.
4235 *
4236 * Returns 0 if suceeds and -1 if an internal error occurs.
4237 */
4238static int
4239xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4240 xmlSchemaTypePtr item)
4241{
4242 static int growSize = 100;
4243 xmlSchemaAssemblePtr ass;
4244
4245 ass = ctxt->assemble;
4246 if (ass->sizeItems < 0) {
4247 /* If disabled. */
4248 return (0);
4249 }
4250 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004251 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004252 if (ass->items == NULL) {
4253 xmlSchemaPErrMemory(ctxt,
4254 "allocating new item buffer", NULL);
4255 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004256 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004257 ass->sizeItems = growSize;
4258 } else if (ass->sizeItems <= ass->nbItems) {
4259 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004260 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004261 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4262 if (ass->items == NULL) {
4263 xmlSchemaPErrMemory(ctxt,
4264 "growing item buffer", NULL);
4265 ass->sizeItems = 0;
4266 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004267 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004268 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004269 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004270 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4271 return (0);
4272}
4273
4274/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004275 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004276 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004277 * @schema: the schema being built
4278 * @name: the item name
4279 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004280 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004281 * *WARNING* this interface is highly subject to change
4282 *
4283 * Returns the new struture or NULL in case of error
4284 */
4285static xmlSchemaNotationPtr
4286xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004287 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004288{
4289 xmlSchemaNotationPtr ret = NULL;
4290 int val;
4291
4292 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4293 return (NULL);
4294
4295 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004296 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 if (schema->notaDecl == NULL)
4298 return (NULL);
4299
4300 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4301 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004302 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004303 return (NULL);
4304 }
4305 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004306 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4308 ret);
4309 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004310 /*
4311 * TODO: This should never happen, since a unique name will be computed.
4312 * If it fails, then an other internal error must have occured.
4313 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004314 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4315 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004316 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004317 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004318 xmlFree(ret);
4319 return (NULL);
4320 }
4321 return (ret);
4322}
4323
4324
4325/**
4326 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004327 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004328 * @schema: the schema being built
4329 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004330 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004331 *
4332 * Add an XML schema Attrribute declaration
4333 * *WARNING* this interface is highly subject to change
4334 *
4335 * Returns the new struture or NULL in case of error
4336 */
4337static xmlSchemaAttributePtr
4338xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004339 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004340 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004341{
4342 xmlSchemaAttributePtr ret = NULL;
4343 int val;
4344
4345 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4346 return (NULL);
4347
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004348#ifdef DEBUG
4349 fprintf(stderr, "Adding attribute %s\n", name);
4350 if (namespace != NULL)
4351 fprintf(stderr, " target namespace %s\n", namespace);
4352#endif
4353
Daniel Veillard4255d502002-04-16 15:50:10 +00004354 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004355 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004356 if (schema->attrDecl == NULL)
4357 return (NULL);
4358
4359 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4360 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004361 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004362 return (NULL);
4363 }
4364 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004365 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004366 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004367 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004368 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004369 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004370 if (topLevel) {
4371 xmlSchemaPCustomErr(ctxt,
4372 XML_SCHEMAP_REDEFINED_ATTR,
4373 NULL, NULL, node,
4374 "A global attribute declaration with the name '%s' does "
4375 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004376 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004377 return (NULL);
4378 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004379 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004380 /*
4381 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4382 * in the scenario:
4383 * 1. multiple top-level complex types have different target
4384 * namespaces but have the SAME NAME; this can happen if
4385 * schemata are imported
4386 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004387 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004388 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004389 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004390 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004391 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004392 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004393
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004394 if (val != 0) {
4395 xmlSchemaPCustomErr(ctxt,
4396 XML_SCHEMAP_INTERNAL,
4397 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004398 "Internal error: xmlSchemaAddAttribute, "
4399 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004400 "could not be added to the hash.", name);
4401 xmlFree(ret);
4402 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004403 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004404 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004405 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004406 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004407 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004408 return (ret);
4409}
4410
4411/**
4412 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004413 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004414 * @schema: the schema being built
4415 * @name: the item name
4416 *
4417 * Add an XML schema Attrribute Group declaration
4418 *
4419 * Returns the new struture or NULL in case of error
4420 */
4421static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004422xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004423 xmlSchemaPtr schema, const xmlChar * name,
4424 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004425{
4426 xmlSchemaAttributeGroupPtr ret = NULL;
4427 int val;
4428
4429 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4430 return (NULL);
4431
4432 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004433 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004434 if (schema->attrgrpDecl == NULL)
4435 return (NULL);
4436
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004437 ret =
4438 (xmlSchemaAttributeGroupPtr)
4439 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004440 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004441 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004442 return (NULL);
4443 }
4444 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004445 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004446 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004447 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004448 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004449 xmlSchemaPCustomErr(ctxt,
4450 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4451 NULL, NULL, node,
4452 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004453 xmlFree(ret);
4454 return (NULL);
4455 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004456 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004457 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004458 return (ret);
4459}
4460
4461/**
4462 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004463 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004464 * @schema: the schema being built
4465 * @name: the type name
4466 * @namespace: the type namespace
4467 *
4468 * Add an XML schema Element declaration
4469 * *WARNING* this interface is highly subject to change
4470 *
4471 * Returns the new struture or NULL in case of error
4472 */
4473static xmlSchemaElementPtr
4474xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004475 const xmlChar * name, const xmlChar * namespace,
4476 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004477{
4478 xmlSchemaElementPtr ret = NULL;
4479 int val;
4480
4481 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4482 return (NULL);
4483
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004484#ifdef DEBUG
4485 fprintf(stderr, "Adding element %s\n", name);
4486 if (namespace != NULL)
4487 fprintf(stderr, " target namespace %s\n", namespace);
4488#endif
4489
Daniel Veillard4255d502002-04-16 15:50:10 +00004490 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004491 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004492 if (schema->elemDecl == NULL)
4493 return (NULL);
4494
4495 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4496 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004497 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004498 return (NULL);
4499 }
4500 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004501 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004502 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004503 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004504 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004505 if (topLevel) {
4506 xmlSchemaPCustomErr(ctxt,
4507 XML_SCHEMAP_REDEFINED_ELEMENT,
4508 NULL, NULL, node,
4509 "A global element declaration with the name '%s' does "
4510 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004511 xmlFree(ret);
4512 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004513 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004514 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004515
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004516 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004517 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004518 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004519 if (val != 0) {
4520 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004521 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004522 NULL, NULL, node,
4523 "Internal error: xmlSchemaAddElement, "
4524 "a dublicate element declaration with the name '%s' "
4525 "could not be added to the hash.", name);
4526 xmlFree(ret);
4527 return (NULL);
4528 }
4529 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004530
Daniel Veillard4255d502002-04-16 15:50:10 +00004531 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004532 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004533 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004534 return (ret);
4535}
4536
4537/**
4538 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004539 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004540 * @schema: the schema being built
4541 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004542 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004543 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004544 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004545 * *WARNING* this interface is highly subject to change
4546 *
4547 * Returns the new struture or NULL in case of error
4548 */
4549static xmlSchemaTypePtr
4550xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004551 const xmlChar * name, const xmlChar * namespace,
4552 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004553{
4554 xmlSchemaTypePtr ret = NULL;
4555 int val;
4556
4557 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4558 return (NULL);
4559
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004560#ifdef DEBUG
4561 fprintf(stderr, "Adding type %s\n", name);
4562 if (namespace != NULL)
4563 fprintf(stderr, " target namespace %s\n", namespace);
4564#endif
4565
Daniel Veillard4255d502002-04-16 15:50:10 +00004566 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004567 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004568 if (schema->typeDecl == NULL)
4569 return (NULL);
4570
4571 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4572 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004573 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004574 return (NULL);
4575 }
4576 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004577 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004578 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004579 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004580 if (val != 0) {
4581 if (ctxt->includes == 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004582 xmlSchemaPCustomErr(ctxt,
4583 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004584 NULL, NULL, node,
4585 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004586 xmlFree(ret);
4587 return (NULL);
4588 } else {
4589 xmlSchemaTypePtr prev;
4590
4591 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
4592 if (prev == NULL) {
4593 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004594 XML_ERR_INTERNAL_ERROR,
4595 "Internal error: xmlSchemaAddType, on type "
4596 "'%s'.\n",
4597 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004598 xmlFree(ret);
4599 return (NULL);
4600 }
4601 ret->redef = prev->redef;
4602 prev->redef = ret;
4603 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004604 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004605 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004606 ret->minOccurs = 1;
4607 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004608 ret->attributeUses = NULL;
4609 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004610 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004611 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004612 return (ret);
4613}
4614
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004615static xmlSchemaQNameRefPtr
4616xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4617 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004618 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004619 const xmlChar *refNs)
4620{
4621 xmlSchemaQNameRefPtr ret;
4622
4623 ret = (xmlSchemaQNameRefPtr)
4624 xmlMalloc(sizeof(xmlSchemaQNameRef));
4625 if (ret == NULL) {
4626 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4627 NULL);
4628 return (NULL);
4629 }
4630 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4631 ret->name = refName;
4632 ret->targetNamespace = refNs;
4633 ret->item = NULL;
4634 ret->itemType = refType;
4635 /*
4636 * Store the reference item in the schema.
4637 */
4638 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4639 return (ret);
4640}
4641
4642/**
4643 * xmlSchemaAddModelGroup:
4644 * @ctxt: a schema parser context
4645 * @schema: the schema being built
4646 * @type: the "compositor" type of the model group
4647 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004648 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004649 *
4650 * Adds a schema model group
4651 * *WARNING* this interface is highly subject to change
4652 *
4653 * Returns the new struture or NULL in case of error
4654 */
4655static xmlSchemaModelGroupPtr
4656xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4657 xmlSchemaTypeType type, const xmlChar **container,
4658 xmlNodePtr node)
4659{
4660 xmlSchemaModelGroupPtr ret = NULL;
4661 xmlChar buf[30];
4662
4663 if ((ctxt == NULL) || (schema == NULL))
4664 return (NULL);
4665
4666#ifdef DEBUG
4667 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004668#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004669 ret = (xmlSchemaModelGroupPtr)
4670 xmlMalloc(sizeof(xmlSchemaModelGroup));
4671 if (ret == NULL) {
4672 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4673 NULL);
4674 return (NULL);
4675 }
4676 ret->type = type;
4677 ret->annot = NULL;
4678 ret->node = node;
4679 ret->children = NULL;
4680 ret->next = NULL;
4681 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4682 if (container != NULL)
4683 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4684 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004685 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004686 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4687 } else {
4688 if (container != NULL)
4689 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4690 }
4691 if (container != NULL)
4692 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4693 /*
4694 * Add to volatile items.
4695 * TODO: this should be changed someday.
4696 */
4697 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4698 xmlFree(ret);
4699 return (NULL);
4700 }
4701 return (ret);
4702}
4703
4704
4705/**
4706 * xmlSchemaAddParticle:
4707 * @ctxt: a schema parser context
4708 * @schema: the schema being built
4709 * @node: the corresponding node in the schema doc
4710 * @min: the minOccurs
4711 * @max: the maxOccurs
4712 *
4713 * Adds an XML schema particle component.
4714 * *WARNING* this interface is highly subject to change
4715 *
4716 * Returns the new struture or NULL in case of error
4717 */
4718static xmlSchemaParticlePtr
4719xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4720 xmlNodePtr node, int min, int max)
4721{
4722 xmlSchemaParticlePtr ret = NULL;
4723 if ((ctxt == NULL) || (schema == NULL))
4724 return (NULL);
4725
4726#ifdef DEBUG
4727 fprintf(stderr, "Adding particle component\n");
4728#endif
4729 ret = (xmlSchemaParticlePtr)
4730 xmlMalloc(sizeof(xmlSchemaParticle));
4731 if (ret == NULL) {
4732 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4733 NULL);
4734 return (NULL);
4735 }
4736 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4737 ret->annot = NULL;
4738 ret->node = node;
4739 ret->minOccurs = min;
4740 ret->maxOccurs = max;
4741 ret->next = NULL;
4742 ret->children = NULL;
4743
4744 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4745 xmlFree(ret);
4746 return (NULL);
4747 }
4748 return (ret);
4749}
4750
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004751/**
4752 * xmlSchemaAddGroup:
4753 * @ctxt: a schema validation context
4754 * @schema: the schema being built
4755 * @name: the group name
4756 *
4757 * Add an XML schema Group definition
4758 *
4759 * Returns the new struture or NULL in case of error
4760 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004761static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004762xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004763 const xmlChar *name, const xmlChar *namespaceName,
4764 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004766 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004767 int val;
4768
4769 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4770 return (NULL);
4771
4772 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004773 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004774 if (schema->groupDecl == NULL)
4775 return (NULL);
4776
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004777 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004778 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004779 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004780 return (NULL);
4781 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004782 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004783 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004784 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004785 ret->node = node;
4786 ret->targetNamespace = namespaceName;
4787 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004788 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004789 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00004790 XML_SCHEMAP_REDEFINED_GROUP,
4791 NULL, NULL, node,
4792 "A global model group definition with the name '%s' does already "
4793 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004794 xmlFree(ret);
4795 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004796 }
4797 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004798 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004799 return (ret);
4800}
4801
Daniel Veillard3646d642004-06-02 19:19:14 +00004802/**
4803 * xmlSchemaNewWildcardNs:
4804 * @ctxt: a schema validation context
4805 *
4806 * Creates a new wildcard namespace constraint.
4807 *
4808 * Returns the new struture or NULL in case of error
4809 */
4810static xmlSchemaWildcardNsPtr
4811xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
4812{
4813 xmlSchemaWildcardNsPtr ret;
4814
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004815 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004816 xmlMalloc(sizeof(xmlSchemaWildcardNs));
4817 if (ret == NULL) {
4818 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004819 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00004820 }
4821 ret->value = NULL;
4822 ret->next = NULL;
4823 return (ret);
4824}
4825
4826/**
4827 * xmlSchemaAddWildcard:
4828 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004829 * @schema: a schema
4830 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004831 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004832 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00004833 *
4834 * Returns the new struture or NULL in case of error
4835 */
4836static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004837xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4838 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00004839{
4840 xmlSchemaWildcardPtr ret = NULL;
4841
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004842 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00004843 return (NULL);
4844
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004845#ifdef DEBUG
4846 fprintf(stderr, "Adding wildcard component\n");
4847#endif
4848
Daniel Veillard3646d642004-06-02 19:19:14 +00004849 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
4850 if (ret == NULL) {
4851 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
4852 return (NULL);
4853 }
4854 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004855 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00004856 ret->minOccurs = 1;
4857 ret->maxOccurs = 1;
4858
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004859 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4860 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
4861 "Failed to add a wildcard component to the list", NULL);
4862 xmlFree(ret);
4863 return (NULL);
4864 }
Daniel Veillard3646d642004-06-02 19:19:14 +00004865 return (ret);
4866}
4867
Daniel Veillard4255d502002-04-16 15:50:10 +00004868/************************************************************************
4869 * *
4870 * Utilities for parsing *
4871 * *
4872 ************************************************************************/
4873
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004874#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00004875/**
4876 * xmlGetQNameProp:
4877 * @ctxt: a schema validation context
4878 * @node: a subtree containing XML Schema informations
4879 * @name: the attribute name
4880 * @namespace: the result namespace if any
4881 *
4882 * Extract a QName Attribute value
4883 *
4884 * Returns the NCName or NULL if not found, and also update @namespace
4885 * with the namespace URI
4886 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004887static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00004888xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004889 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004890{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004891 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004892 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004893 const xmlChar *ret, *prefix;
4894 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004895 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004896
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004897 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004898 attr = xmlSchemaGetPropNode(node, name);
4899 if (attr == NULL)
4900 return (NULL);
4901 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004902
Daniel Veillard4255d502002-04-16 15:50:10 +00004903 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004904 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004905
Daniel Veillardba0153a2004-04-01 10:42:31 +00004906 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00004907 ns = xmlSearchNs(node->doc, node, 0);
4908 if (ns) {
4909 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
4910 return (val);
4911 }
4912 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004913 ret = xmlSplitQName3(val, &len);
4914 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004915 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004916 }
4917 ret = xmlDictLookup(ctxt->dict, ret, -1);
4918 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00004919
4920 ns = xmlSearchNs(node->doc, node, prefix);
4921 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004922 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
4923 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00004924 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004925 "The QName value '%s' has no corresponding namespace "
4926 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004927 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004928 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004929 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004930 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004931}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00004932#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00004933
4934/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004935 * xmlSchemaPValAttrNodeQNameValue:
4936 * @ctxt: a schema parser context
4937 * @schema: the schema context
4938 * @ownerDes: the designation of the parent element
4939 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004940 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00004941 * @local: the resulting local part if found, the attribute value otherwise
4942 * @uri: the resulting namespace URI if found
4943 *
4944 * Extracts the local name and the URI of a QName value and validates it.
4945 * This one is intended to be used on attribute values that
4946 * should resolve to schema components.
4947 *
4948 * Returns 0, in case the QName is valid, a positive error code
4949 * if not valid and -1 if an internal error occurs.
4950 */
4951static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004952xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004953 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004954 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004955 xmlSchemaTypePtr ownerItem,
4956 xmlAttrPtr attr,
4957 const xmlChar *value,
4958 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004959 const xmlChar **local)
4960{
4961 const xmlChar *pref;
4962 xmlNsPtr ns;
4963 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004964
Daniel Veillardc0826a72004-08-10 14:17:33 +00004965 *uri = NULL;
4966 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004967 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004968 if (ret > 0) {
4969 xmlSchemaPSimpleTypeErr(ctxt,
4970 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4971 ownerItem, (xmlNodePtr) attr,
4972 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4973 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004974 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004975 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004976 } else if (ret < 0)
4977 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004978
4979 if (!strchr((char *) value, ':')) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004980 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4981 if (ns)
4982 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4983 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4984 /*
4985 * This one takes care of included schemas with no
4986 * target namespace.
4987 */
4988 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004989 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004990 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004991 return (0);
4992 }
4993 /*
4994 * At this point xmlSplitQName3 has to return a local name.
4995 */
4996 *local = xmlSplitQName3(value, &len);
4997 *local = xmlDictLookup(ctxt->dict, *local, -1);
4998 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004999 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5000 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005001 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005002 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005003 ownerItem, (xmlNodePtr) attr,
5004 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5005 "The value '%s' of simple type 'xs:QName' has no "
5006 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005007 return (ctxt->err);
5008 } else {
5009 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005010 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005011 return (0);
5012}
5013
5014/**
5015 * xmlSchemaPValAttrNodeQName:
5016 * @ctxt: a schema parser context
5017 * @schema: the schema context
5018 * @ownerDes: the designation of the owner element
5019 * @ownerItem: the owner as a schema object
5020 * @attr: the attribute node
5021 * @local: the resulting local part if found, the attribute value otherwise
5022 * @uri: the resulting namespace URI if found
5023 *
5024 * Extracts and validates the QName of an attribute value.
5025 * This one is intended to be used on attribute values that
5026 * should resolve to schema components.
5027 *
5028 * Returns 0, in case the QName is valid, a positive error code
5029 * if not valid and -1 if an internal error occurs.
5030 */
5031static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005032xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005033 xmlSchemaPtr schema,
5034 xmlChar **ownerDes,
5035 xmlSchemaTypePtr ownerItem,
5036 xmlAttrPtr attr,
5037 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005038 const xmlChar **local)
5039{
5040 const xmlChar *value;
5041
5042 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005043 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5044 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005045}
5046
5047/**
5048 * xmlSchemaPValAttrQName:
5049 * @ctxt: a schema parser context
5050 * @schema: the schema context
5051 * @ownerDes: the designation of the parent element
5052 * @ownerItem: the owner as a schema object
5053 * @ownerElem: the parent node of the attribute
5054 * @name: the name of the attribute
5055 * @local: the resulting local part if found, the attribute value otherwise
5056 * @uri: the resulting namespace URI if found
5057 *
5058 * Extracts and validates the QName of an attribute value.
5059 *
5060 * Returns 0, in case the QName is valid, a positive error code
5061 * if not valid and -1 if an internal error occurs.
5062 */
5063static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005064xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5065 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005066 xmlChar **ownerDes,
5067 xmlSchemaTypePtr ownerItem,
5068 xmlNodePtr ownerElem,
5069 const char *name,
5070 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005071 const xmlChar **local)
5072{
5073 xmlAttrPtr attr;
5074
5075 attr = xmlSchemaGetPropNode(ownerElem, name);
5076 if (attr == NULL) {
5077 *local = NULL;
5078 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005079 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005080 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005081 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5082 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005083}
5084
5085/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005086 * xmlSchemaPValAttrID:
5087 * @ctxt: a schema parser context
5088 * @schema: the schema context
5089 * @ownerDes: the designation of the parent element
5090 * @ownerItem: the owner as a schema object
5091 * @ownerElem: the parent node of the attribute
5092 * @name: the name of the attribute
5093 *
5094 * Extracts and validates the ID of an attribute value.
5095 *
5096 * Returns 0, in case the ID is valid, a positive error code
5097 * if not valid and -1 if an internal error occurs.
5098 */
5099static int
5100xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005101 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005102 xmlSchemaTypePtr ownerItem,
5103 xmlNodePtr ownerElem,
5104 const xmlChar *name)
5105{
5106 int ret;
5107 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005108 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005109
5110 value = xmlGetNoNsProp(ownerElem, name);
5111 if (value == NULL)
5112 return (0);
5113
5114 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5115 if (attr == NULL)
5116 return (-1);
5117
5118 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005119 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005120 /*
5121 * NOTE: the IDness might have already be declared in the DTD
5122 */
5123 if (attr->atype != XML_ATTRIBUTE_ID) {
5124 xmlIDPtr res;
5125 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005126
5127 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005128 * TODO: Use xmlSchemaStrip here; it's not exported at this
5129 * moment.
5130 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005131 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005132 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005133 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005134 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5135 if (res == NULL) {
5136 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005137 xmlSchemaPSimpleTypeErr(ctxt,
5138 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5139 ownerItem, (xmlNodePtr) attr,
5140 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5141 NULL, NULL, "Duplicate value '%s' of simple "
5142 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005143 } else
5144 attr->atype = XML_ATTRIBUTE_ID;
5145 if (strip != NULL)
5146 xmlFree(strip);
5147 }
5148 } else if (ret > 0) {
5149 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005150 xmlSchemaPSimpleTypeErr(ctxt,
5151 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5152 ownerItem, (xmlNodePtr) attr,
5153 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5154 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5155 "not a valid 'xs:NCName'",
5156 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005157 }
5158 xmlFree(value);
5159
5160 return (ret);
5161}
5162
5163/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005164 * xmlGetMaxOccurs:
5165 * @ctxt: a schema validation context
5166 * @node: a subtree containing XML Schema informations
5167 *
5168 * Get the maxOccurs property
5169 *
5170 * Returns the default if not found, or the value
5171 */
5172static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005173xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5174 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005175{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005176 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005177 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005178 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005179
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005180 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5181 if (attr == NULL)
5182 return (def);
5183 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005184
5185 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005186 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005187 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005188 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5189 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005190 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005191 val, NULL, NULL, NULL);
5192 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005193 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005194 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005195 }
5196
5197 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005198 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005199 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005200 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005201 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005202 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5203 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005204 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005205 val, NULL, NULL, NULL);
5206 return (def);
5207 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005208 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005209 ret = ret * 10 + (*cur - '0');
5210 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005211 }
William M. Brack76e95df2003-10-18 16:20:14 +00005212 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005213 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005214 /*
5215 * TODO: Restrict the maximal value to Integer.
5216 */
5217 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005218 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005219 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5220 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005221 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005222 val, NULL, NULL, NULL);
5223 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005224 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005225 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005226}
5227
5228/**
5229 * xmlGetMinOccurs:
5230 * @ctxt: a schema validation context
5231 * @node: a subtree containing XML Schema informations
5232 *
5233 * Get the minOccurs property
5234 *
5235 * Returns the default if not found, or the value
5236 */
5237static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005238xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005239 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005240{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005241 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005242 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005243 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005244
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005245 attr = xmlSchemaGetPropNode(node, "minOccurs");
5246 if (attr == NULL)
5247 return (def);
5248 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005249 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005250 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005251 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005252 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005253 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005254 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5255 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005256 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005257 val, NULL, NULL, NULL);
5258 return (def);
5259 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005260 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005261 ret = ret * 10 + (*cur - '0');
5262 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005263 }
William M. Brack76e95df2003-10-18 16:20:14 +00005264 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005265 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005266 /*
5267 * TODO: Restrict the maximal value to Integer.
5268 */
5269 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005270 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005271 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5272 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005273 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005274 val, NULL, NULL, NULL);
5275 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005276 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005277 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005278}
5279
5280/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005281 * xmlSchemaPGetBoolNodeValue:
5282 * @ctxt: a schema validation context
5283 * @ownerDes: owner designation
5284 * @ownerItem: the owner as a schema item
5285 * @node: the node holding the value
5286 *
5287 * Converts a boolean string value into 1 or 0.
5288 *
5289 * Returns 0 or 1.
5290 */
5291static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005292xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5293 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005294 xmlSchemaTypePtr ownerItem,
5295 xmlNodePtr node)
5296{
5297 xmlChar *value = NULL;
5298 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005299
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005300 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005301 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005302 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005303 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005304 * can have the following legal literals {true, false, 1, 0}.
5305 */
5306 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5307 res = 1;
5308 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5309 res = 0;
5310 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5311 res = 1;
5312 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005313 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005314 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005315 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005316 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005317 ownerItem, node,
5318 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5319 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005320 NULL, NULL, NULL);
5321 }
5322 if (value != NULL)
5323 xmlFree(value);
5324 return (res);
5325}
5326
5327/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005328 * xmlGetBooleanProp:
5329 * @ctxt: a schema validation context
5330 * @node: a subtree containing XML Schema informations
5331 * @name: the attribute name
5332 * @def: the default value
5333 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005334 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005335 *
5336 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005337 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005338 */
5339static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005340xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5341 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005342 xmlSchemaTypePtr ownerItem,
5343 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005344 const char *name, int def)
5345{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005346 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005347
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005348 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005349 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005350 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005351 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005353 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005354 * can have the following legal literals {true, false, 1, 0}.
5355 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005356 if (xmlStrEqual(val, BAD_CAST "true"))
5357 def = 1;
5358 else if (xmlStrEqual(val, BAD_CAST "false"))
5359 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005360 else if (xmlStrEqual(val, BAD_CAST "1"))
5361 def = 1;
5362 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005363 def = 0;
5364 else {
5365 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005366 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005367 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005368 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005369 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5370 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005371 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005372 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005373}
5374
5375/************************************************************************
5376 * *
5377 * Shema extraction from an Infoset *
5378 * *
5379 ************************************************************************/
5380static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5381 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005382 xmlNodePtr node,
5383 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005384static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5385 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005386 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005387 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005388 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005389static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5390 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005391 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005392 xmlNodePtr node,
5393 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005394static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5395 ctxt,
5396 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005397 xmlNodePtr node,
5398 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005399static xmlSchemaAttributeGroupPtr
5400xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005401 xmlSchemaPtr schema, xmlNodePtr node,
5402 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005403static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5404 xmlSchemaPtr schema,
5405 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005406static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005407xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5408 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005409
5410/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005411 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005412 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005413 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005414 * @ownerDes: the designation of the parent element
5415 * @ownerItem: the schema object owner if existent
5416 * @attr: the schema attribute node being validated
5417 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005418 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005419 *
5420 * Validates a value against the given built-in type.
5421 * This one is intended to be used internally for validation
5422 * of schema attribute values during parsing of the schema.
5423 *
5424 * Returns 0 if the value is valid, a positive error code
5425 * number otherwise and -1 in case of an internal or API error.
5426 */
5427static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005428xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5429 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5430 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005431 xmlAttrPtr attr,
5432 const xmlChar *value,
5433 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005434{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005435
5436 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005437
5438 /*
5439 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5440 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005441 */
5442 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005443 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005444 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5445 PERROR_INT("xmlSchemaPValAttrNodeValue",
5446 "the given type is not a built-in type");
5447 return (-1);
5448 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005449 switch (type->builtInType) {
5450 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005451 case XML_SCHEMAS_QNAME:
5452 case XML_SCHEMAS_ANYURI:
5453 case XML_SCHEMAS_TOKEN:
5454 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005455 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5456 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005457 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005458 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005459 PERROR_INT("xmlSchemaPValAttrNodeValue",
5460 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005461 return (-1);
5462 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005463 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005464 /*
5465 * TODO: Should we use the S4S error codes instead?
5466 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005467 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005468 PERROR_INT("xmlSchemaPValAttrNodeValue",
5469 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005470 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005471 } else if (ret > 0) {
5472 if (VARIETY_LIST(type))
5473 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5474 else
5475 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5476 xmlSchemaPSimpleTypeErr(pctxt,
5477 ret, ownerItem, (xmlNodePtr) attr,
5478 type, NULL, value, NULL, NULL, NULL);
5479 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005480 return (ret);
5481}
5482
5483/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005484 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005485 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005486 * @ctxt: a schema parser context
5487 * @ownerDes: the designation of the parent element
5488 * @ownerItem: the schema object owner if existent
5489 * @attr: the schema attribute node being validated
5490 * @type: the built-in type to be validated against
5491 * @value: the resulting value if any
5492 *
5493 * Extracts and validates a value against the given built-in type.
5494 * This one is intended to be used internally for validation
5495 * of schema attribute values during parsing of the schema.
5496 *
5497 * Returns 0 if the value is valid, a positive error code
5498 * number otherwise and -1 in case of an internal or API error.
5499 */
5500static int
5501xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5502 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005503 xmlSchemaTypePtr ownerItem,
5504 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005505 xmlSchemaTypePtr type,
5506 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005507{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005508 const xmlChar *val;
5509
5510 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005511 return (-1);
5512
Daniel Veillardc0826a72004-08-10 14:17:33 +00005513 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5514 if (value != NULL)
5515 *value = val;
5516
5517 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005518 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005519}
5520
5521/**
5522 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005523 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005524 * @ctxt: a schema parser context
5525 * @node: the element node of the attribute
5526 * @ownerDes: the designation of the parent element
5527 * @ownerItem: the schema object owner if existent
5528 * @ownerElem: the owner element node
5529 * @name: the name of the schema attribute node
5530 * @type: the built-in type to be validated against
5531 * @value: the resulting value if any
5532 *
5533 * Extracts and validates a value against the given built-in type.
5534 * This one is intended to be used internally for validation
5535 * of schema attribute values during parsing of the schema.
5536 *
5537 * Returns 0 if the value is valid, a positive error code
5538 * number otherwise and -1 in case of an internal or API error.
5539 */
5540static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005541xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005542 xmlChar **ownerDes,
5543 xmlSchemaTypePtr ownerItem,
5544 xmlNodePtr ownerElem,
5545 const char *name,
5546 xmlSchemaTypePtr type,
5547 const xmlChar **value)
5548{
5549 xmlAttrPtr attr;
5550
5551 if ((ctxt == NULL) || (type == NULL)) {
5552 if (value != NULL)
5553 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005554 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005555 }
5556 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5557 if (value != NULL)
5558 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005559 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005560 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005561 "Internal error: xmlSchemaPValAttr, the given "
5562 "type '%s' is not a built-in type.\n",
5563 type->name, NULL);
5564 return (-1);
5565 }
5566 attr = xmlSchemaGetPropNode(ownerElem, name);
5567 if (attr == NULL) {
5568 if (value != NULL)
5569 *value = NULL;
5570 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005571 }
5572 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005573 type, value));
5574}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005575
5576static int
5577xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5578 xmlSchemaPtr schema,
5579 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005580 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005581 const xmlChar *namespaceName)
5582{
5583 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005584 return (1);
5585 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5586 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005587 if (pctxt->localImports != NULL) {
5588 int i;
5589 for (i = 0; i < pctxt->nbLocalImports; i++)
5590 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5591 return (1);
5592 }
5593 if (namespaceName == NULL)
5594 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005595 NULL, (xmlSchemaTypePtr) item, node,
5596 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005597 "namespace are not valid, since not indicated by an import "
5598 "statement", NULL);
5599 else
5600 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005601 NULL, (xmlSchemaTypePtr) item, node,
5602 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005603 "namespace '%s' are not valid, since not indicated by an import "
5604 "statement", namespaceName);
5605 return (0);
5606}
5607
Daniel Veillardc0826a72004-08-10 14:17:33 +00005608/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005609 * xmlSchemaParseAttrDecls:
5610 * @ctxt: a schema validation context
5611 * @schema: the schema being built
5612 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005613 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005614 *
5615 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005616 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005617 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5618 */
5619static xmlNodePtr
5620xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5621 xmlNodePtr child, xmlSchemaTypePtr type)
5622{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005623 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005624
Daniel Veillard4255d502002-04-16 15:50:10 +00005625 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626 (IS_SCHEMA(child, "attributeGroup"))) {
5627 attr = NULL;
5628 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005629 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005630 } else if (IS_SCHEMA(child, "attributeGroup")) {
5631 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005632 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005633 }
5634 if (attr != NULL) {
5635 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005636 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5637 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5638 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005639 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005640 lastattr = attr;
5641 } else {
5642 lastattr->next = attr;
5643 lastattr = attr;
5644 }
5645 }
5646 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005647 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005648 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005649}
5650
5651/**
5652 * xmlSchemaParseAnnotation:
5653 * @ctxt: a schema validation context
5654 * @schema: the schema being built
5655 * @node: a subtree containing XML Schema informations
5656 *
5657 * parse a XML schema Attrribute declaration
5658 * *WARNING* this interface is highly subject to change
5659 *
William M. Bracke7091952004-05-11 15:09:58 +00005660 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 * 1 in case of success.
5662 */
5663static xmlSchemaAnnotPtr
5664xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5665 xmlNodePtr node)
5666{
5667 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005668 xmlNodePtr child = NULL;
5669 xmlAttrPtr attr;
5670 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005671
Daniel Veillardc0826a72004-08-10 14:17:33 +00005672 /*
5673 * INFO: S4S completed.
5674 */
5675 /*
5676 * id = ID
5677 * {any attributes with non-schema namespace . . .}>
5678 * Content: (appinfo | documentation)*
5679 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005680 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5681 return (NULL);
5682 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005683 attr = node->properties;
5684 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005685 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005686 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005687 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005688 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005689
5690 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005691 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5692 NULL, NULL, attr);
5693 }
5694 attr = attr->next;
5695 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005696 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005697 /*
5698 * And now for the children...
5699 */
5700 child = node->children;
5701 while (child != NULL) {
5702 if (IS_SCHEMA(child, "appinfo")) {
5703 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005704 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005705 * source = anyURI
5706 * {any attributes with non-schema namespace . . .}>
5707 * Content: ({any})*
5708 */
5709 attr = child->properties;
5710 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005711 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005712 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005713 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005714 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005715
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005716 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005717 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5718 NULL, NULL, attr);
5719 }
5720 attr = attr->next;
5721 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005722 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5723 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005724 child = child->next;
5725 } else if (IS_SCHEMA(child, "documentation")) {
5726 /* TODO: make available the content of "documentation". */
5727 /*
5728 * source = anyURI
5729 * {any attributes with non-schema namespace . . .}>
5730 * Content: ({any})*
5731 */
5732 attr = child->properties;
5733 while (attr != NULL) {
5734 if (attr->ns == NULL) {
5735 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005736 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005737 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5738 NULL, NULL, attr);
5739 }
5740 } else {
5741 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5742 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5743 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005744
5745 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005746 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5747 NULL, NULL, attr);
5748 }
5749 }
5750 attr = attr->next;
5751 }
5752 /*
5753 * Attribute "xml:lang".
5754 */
5755 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5756 if (attr != NULL)
5757 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005758 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005759 child = child->next;
5760 } else {
5761 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005762 xmlSchemaPContentErr(ctxt,
5763 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005764 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
5765 barked = 1;
5766 child = child->next;
5767 }
5768 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005769
Daniel Veillard4255d502002-04-16 15:50:10 +00005770 return (ret);
5771}
5772
5773/**
5774 * xmlSchemaParseFacet:
5775 * @ctxt: a schema validation context
5776 * @schema: the schema being built
5777 * @node: a subtree containing XML Schema informations
5778 *
5779 * parse a XML schema Facet declaration
5780 * *WARNING* this interface is highly subject to change
5781 *
5782 * Returns the new type structure or NULL in case of error
5783 */
5784static xmlSchemaFacetPtr
5785xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005786 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005787{
5788 xmlSchemaFacetPtr facet;
5789 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005790 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00005791
5792 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5793 return (NULL);
5794
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00005795 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005796 if (facet == NULL) {
5797 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
5798 return (NULL);
5799 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005800 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005801 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00005802 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005803 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
5804 "Facet %s has no value\n", node->name, NULL);
5805 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00005806 return (NULL);
5807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005808 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005809 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005810 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005811 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005812 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005813 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005814 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005815 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005816 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005817 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005818 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005819 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005820 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005821 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005822 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005823 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005824 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005825 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005826 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005827 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005828 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005829 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
5830 } else if (IS_SCHEMA(node, "minLength")) {
5831 facet->type = XML_SCHEMA_FACET_MINLENGTH;
5832 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005833 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
5834 "Unknown facet type %s\n", node->name, NULL);
5835 xmlSchemaFreeFacet(facet);
5836 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005837 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005838 xmlSchemaPValAttrID(ctxt, NULL,
5839 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00005840 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005841 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
5842 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
5843 const xmlChar *fixed;
5844
5845 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
5846 if (fixed != NULL) {
5847 if (xmlStrEqual(fixed, BAD_CAST "true"))
5848 facet->fixed = 1;
5849 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005850 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005851 child = node->children;
5852
5853 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005854 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5855 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005856 }
5857 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005858 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
5859 "Facet %s has unexpected child content\n",
5860 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005861 }
5862 return (facet);
5863}
5864
5865/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005866 * xmlSchemaParseWildcardNs:
5867 * @ctxt: a schema parser context
5868 * @wildc: the wildcard, already created
5869 * @node: a subtree containing XML Schema informations
5870 *
5871 * Parses the attribute "processContents" and "namespace"
5872 * of a xsd:anyAttribute and xsd:any.
5873 * *WARNING* this interface is highly subject to change
5874 *
5875 * Returns 0 if everything goes fine, a positive error code
5876 * if something is not valid and -1 if an internal error occurs.
5877 */
5878static int
5879xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
5880 xmlSchemaPtr schema,
5881 xmlSchemaWildcardPtr wildc,
5882 xmlNodePtr node)
5883{
5884 const xmlChar *pc, *ns, *dictnsItem;
5885 int ret = 0;
5886 xmlChar *nsItem;
5887 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
5888 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005889
Daniel Veillardc0826a72004-08-10 14:17:33 +00005890 pc = xmlSchemaGetProp(ctxt, node, "processContents");
5891 if ((pc == NULL)
5892 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
5893 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
5894 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
5895 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
5896 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
5897 wildc->processContents = XML_SCHEMAS_ANY_LAX;
5898 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005899 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005900 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005901 NULL, node,
5902 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005903 NULL, NULL, NULL);
5904 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005905 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005906 }
5907 /*
5908 * Build the namespace constraints.
5909 */
5910 attr = xmlSchemaGetPropNode(node, "namespace");
5911 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00005912 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00005913 wildc->any = 1;
5914 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
5915 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005916 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005917 return (-1);
5918 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005919 wildc->negNsSet->value = schema->targetNamespace;
5920 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005921 const xmlChar *end, *cur;
5922
5923 cur = ns;
5924 do {
5925 while (IS_BLANK_CH(*cur))
5926 cur++;
5927 end = cur;
5928 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5929 end++;
5930 if (end == cur)
5931 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005932 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005933 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
5934 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005935 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005936 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005937 NULL, (xmlNodePtr) attr,
5938 NULL,
5939 "((##any | ##other) | List of (xs:anyURI | "
5940 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005941 nsItem, NULL, NULL, NULL);
5942 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
5943 } else {
5944 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
5945 dictnsItem = schema->targetNamespace;
5946 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
5947 dictnsItem = NULL;
5948 } else {
5949 /*
5950 * Validate the item (anyURI).
5951 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005952 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005953 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
5954 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
5955 }
5956 /*
5957 * Avoid dublicate namespaces.
5958 */
5959 tmp = wildc->nsSet;
5960 while (tmp != NULL) {
5961 if (dictnsItem == tmp->value)
5962 break;
5963 tmp = tmp->next;
5964 }
5965 if (tmp == NULL) {
5966 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
5967 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005968 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005969 return (-1);
5970 }
5971 tmp->value = dictnsItem;
5972 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005973 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00005974 wildc->nsSet = tmp;
5975 else
5976 lastNs->next = tmp;
5977 lastNs = tmp;
5978 }
5979
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005980 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005981 xmlFree(nsItem);
5982 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005983 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005984 }
5985 return (ret);
5986}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005987
5988static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005989xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
5990 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005991 xmlNodePtr node,
5992 int minOccurs,
5993 int maxOccurs) {
5994
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005995 if ((maxOccurs == 0) && ( minOccurs == 0))
5996 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005997 if (maxOccurs != UNBOUNDED) {
5998 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005999 * TODO: Maybe we should better not create the particle,
6000 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006001 * content model.
6002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006003 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006004 * 3.9.6 Schema Component Constraint: Particle Correct
6005 *
6006 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006007 if (maxOccurs < 1) {
6008 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006009 * 2.2 {max occurs} must be greater than or equal to 1.
6010 */
6011 xmlSchemaPCustomAttrErr(ctxt,
6012 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006013 NULL, NULL,
6014 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006015 "The value must be greater than or equal to 1");
6016 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6017 } else if (minOccurs > maxOccurs) {
6018 /*
6019 * 2.1 {min occurs} must not be greater than {max occurs}.
6020 */
6021 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006022 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006023 NULL, NULL,
6024 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006025 "The value must not be greater than the value of 'maxOccurs'");
6026 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006028 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006029 return (0);
6030}
6031
Daniel Veillardc0826a72004-08-10 14:17:33 +00006032/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006033 * xmlSchemaParseAny:
6034 * @ctxt: a schema validation context
6035 * @schema: the schema being built
6036 * @node: a subtree containing XML Schema informations
6037 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006038 * Parsea a XML schema <any> element. A particle and wildcard
6039 * will be created (except if minOccurs==maxOccurs==0, in this case
6040 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006041 * *WARNING* this interface is highly subject to change
6042 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006043 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006044 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006045static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006046xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6047 xmlNodePtr node)
6048{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006049 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006050 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006051 xmlSchemaWildcardPtr wild;
6052 int min, max;
6053 xmlAttrPtr attr;
6054 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006055
6056 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6057 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006058 /*
6059 * Check for illegal attributes.
6060 */
6061 attr = node->properties;
6062 while (attr != NULL) {
6063 if (attr->ns == NULL) {
6064 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6065 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6066 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6067 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6068 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006069 xmlSchemaPIllegalAttrErr(ctxt,
6070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6071 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006072 }
6073 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006074 xmlSchemaPIllegalAttrErr(ctxt,
6075 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6076 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006077 }
6078 attr = attr->next;
6079 }
6080 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6081 /*
6082 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006083 */
6084 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6085 "(xs:nonNegativeInteger | unbounded)");
6086 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6087 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006088 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6089 /*
6090 * Create & parse the wildcard.
6091 */
6092 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6093 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006094 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006095 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006096 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006097 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006098 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006099 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006100 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006101 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006102 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006103 }
6104 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006105 xmlSchemaPContentErr(ctxt,
6106 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006107 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006108 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006109 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006110 /*
6111 * No component if minOccurs==maxOccurs==0.
6112 */
6113 if ((min == 0) && (max == 0)) {
6114 /* Don't free the wildcard, since it's already on the list. */
6115 return (NULL);
6116 }
6117 /*
6118 * Create the particle.
6119 */
6120 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6121 if (particle == NULL)
6122 return (NULL);
6123 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006124 wild->minOccurs = min;
6125 wild->maxOccurs = max;
6126 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006127
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006128 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006129}
6130
6131/**
6132 * xmlSchemaParseNotation:
6133 * @ctxt: a schema validation context
6134 * @schema: the schema being built
6135 * @node: a subtree containing XML Schema informations
6136 *
6137 * parse a XML schema Notation declaration
6138 *
6139 * Returns the new structure or NULL in case of error
6140 */
6141static xmlSchemaNotationPtr
6142xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006143 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006144{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006145 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006146 xmlSchemaNotationPtr ret;
6147 xmlNodePtr child = NULL;
6148
6149 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6150 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006151 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006152 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006153 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6154 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006155 return (NULL);
6156 }
6157 ret = xmlSchemaAddNotation(ctxt, schema, name);
6158 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006159 return (NULL);
6160 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006161 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006162
6163 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6164 node, BAD_CAST "id");
6165
6166 if (IS_SCHEMA(child, "annotation")) {
6167 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6168 child = child->next;
6169 }
6170
Daniel Veillard4255d502002-04-16 15:50:10 +00006171 child = node->children;
6172 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006173 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6174 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006175 }
6176 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006177 xmlSchemaPContentErr(ctxt,
6178 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006179 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006180 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006181 }
6182
6183 return (ret);
6184}
6185
6186/**
6187 * xmlSchemaParseAnyAttribute:
6188 * @ctxt: a schema validation context
6189 * @schema: the schema being built
6190 * @node: a subtree containing XML Schema informations
6191 *
6192 * parse a XML schema AnyAttrribute declaration
6193 * *WARNING* this interface is highly subject to change
6194 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006195 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006196 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006197static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006198xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6199 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006200{
Daniel Veillard3646d642004-06-02 19:19:14 +00006201 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006202 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006203 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006204
6205 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6206 return (NULL);
6207
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006208 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6209 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006210 if (ret == NULL) {
6211 return (NULL);
6212 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006213 /*
6214 * Check for illegal attributes.
6215 */
6216 attr = node->properties;
6217 while (attr != NULL) {
6218 if (attr->ns == NULL) {
6219 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6220 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6221 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006222 xmlSchemaPIllegalAttrErr(ctxt,
6223 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6224 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006225 }
6226 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006227 xmlSchemaPIllegalAttrErr(ctxt,
6228 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6229 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006230 }
6231 attr = attr->next;
6232 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006233 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6234 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006235 /*
6236 * Parse the namespace list.
6237 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006238 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006239 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006240 /*
6241 * And now for the children...
6242 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006243 child = node->children;
6244 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006245 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6246 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006247 }
6248 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006249 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006250 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006251 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006252 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006253 }
6254
6255 return (ret);
6256}
6257
6258
6259/**
6260 * xmlSchemaParseAttribute:
6261 * @ctxt: a schema validation context
6262 * @schema: the schema being built
6263 * @node: a subtree containing XML Schema informations
6264 *
6265 * parse a XML schema Attrribute declaration
6266 * *WARNING* this interface is highly subject to change
6267 *
William M. Bracke7091952004-05-11 15:09:58 +00006268 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006269 */
6270static xmlSchemaAttributePtr
6271xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006272 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006273{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006274 const xmlChar *name, *attrValue;
6275 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006276 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006277 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006278 xmlAttrPtr attr, nameAttr;
6279 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006280
6281 /*
6282 * Note that the w3c spec assumes the schema to be validated with schema
6283 * for schemas beforehand.
6284 *
6285 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006286 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006287
6288 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6289 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006290 attr = xmlSchemaGetPropNode(node, "ref");
6291 nameAttr = xmlSchemaGetPropNode(node, "name");
6292
6293 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006294 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006295 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006296 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006297 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006298 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6299 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 "One of the attributes 'ref' or 'name' must be present");
6301 return (NULL);
6302 }
6303 if ((topLevel) || (attr == NULL)) {
6304 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006305 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6306 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006307 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006308 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006309 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006310 isRef = 1;
6311
Daniel Veillardc0826a72004-08-10 14:17:33 +00006312 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006313 char buf[50];
6314 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006315
6316 /*
6317 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006318 */
6319 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6320 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6321 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006322 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006323 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006324 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006325 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006326 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006327 if (ret == NULL) {
6328 if (repName != NULL)
6329 xmlFree(repName);
6330 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006331 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006332 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6333 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006334 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006335 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006336 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6337 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006338 /*
6339 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6340 */
6341 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006342 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6343 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006344 "ref", "name");
6345 /*
6346 * Check for illegal attributes.
6347 */
6348 attr = node->properties;
6349 while (attr != NULL) {
6350 if (attr->ns == NULL) {
6351 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6352 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006353 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006354 * 3.2.3 : 3.2
6355 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006356 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006357 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006358 xmlSchemaPIllegalAttrErr(ctxt,
6359 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006360 (xmlSchemaTypePtr) ret, attr);
6361 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6362 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6363 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006364 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6365 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006366 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006367 xmlSchemaPIllegalAttrErr(ctxt,
6368 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6369 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006370 }
6371 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006372 xmlSchemaPIllegalAttrErr(ctxt,
6373 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6374 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006375 }
6376 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006377 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006378 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006379 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006380
Daniel Veillardc0826a72004-08-10 14:17:33 +00006381 /*
6382 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006383 */
6384 if (xmlSchemaPValAttrNode(ctxt,
6385 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006386 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6387 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006388 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006389 /*
6390 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6391 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006392 /*
6393 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6394 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 */
6396 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006397 xmlSchemaPSimpleTypeErr(ctxt,
6398 XML_SCHEMAP_NO_XMLNS,
6399 NULL, (xmlNodePtr) nameAttr,
6400 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6401 "The value of type 'xs:NCName' must not match 'xmlns'",
6402 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006403 if (repName != NULL)
6404 xmlFree(repName);
6405 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006406 }
6407 /*
6408 * Evaluate the target namespace
6409 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006410 if (topLevel) {
6411 ns = schema->targetNamespace;
6412 } else {
6413 attr = xmlSchemaGetPropNode(node, "form");
6414 if (attr != NULL) {
6415 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6416 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6417 ns = schema->targetNamespace;
6418 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006419 xmlSchemaPSimpleTypeErr(ctxt,
6420 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6421 NULL, (xmlNodePtr) attr,
6422 NULL, "(qualified | unqualified)",
6423 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006424 }
6425 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006426 ns = schema->targetNamespace;
6427 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006428 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006429 if (ret == NULL) {
6430 if (repName != NULL)
6431 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006432 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006433 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006434 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006435 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006436 if (topLevel)
6437 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006438 /*
6439 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6440 * TODO: Move this to the component layer.
6441 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006442 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006443 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006444 XML_SCHEMAP_NO_XSI,
6445 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006446 "The target namespace must not match '%s'",
6447 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006448 }
6449 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006450 * Check for illegal attributes.
6451 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006452 attr = node->properties;
6453 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006454 if (attr->ns == NULL) {
6455 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6456 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6457 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6459 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006460 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006461 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6462 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006463 xmlSchemaPIllegalAttrErr(ctxt,
6464 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6465 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006466 }
6467 }
6468 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006469 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6470 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006471 }
6472 attr = attr->next;
6473 }
6474 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006475 node, "type", &ret->typeNs, &ret->typeName);
6476 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006477 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6478 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006479 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006480 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006481 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006482 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6483 if (ret->defValue != NULL)
6484 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006485 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006486 * Attribute "default".
6487 */
6488 attr = xmlSchemaGetPropNode(node, "default");
6489 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006490 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006491 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006492 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006493 */
6494 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6495 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6496 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6497 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006498 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6499 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006500 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006501 /*
6502 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006503 */
6504 attr = xmlSchemaGetPropNode(node, "use");
6505 if (attr != NULL) {
6506 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6507 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6508 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6509 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6510 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6511 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6512 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6513 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006514 xmlSchemaPSimpleTypeErr(ctxt,
6515 XML_SCHEMAP_INVALID_ATTR_USE,
6516 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6517 NULL, "(optional | prohibited | required)",
6518 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006519 } else
6520 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006521 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006522 * 3.2.3 : 2
6523 * If default and use are both present, use must have
6524 * the actual value optional.
6525 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006526 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6527 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006528 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006529 xmlSchemaPSimpleTypeErr(ctxt,
6530 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6531 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6532 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006533 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006534 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006535 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 /*
6538 * And now for the children...
6539 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006540 child = node->children;
6541 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006542 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6543 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006544 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006545 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006546 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006547 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006548 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006549 * 3.2.3 : 3.2
6550 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006551 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006552 */
6553 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6554 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6555 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006556 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6558 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006559 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006560 }
6561 } else {
6562 if (IS_SCHEMA(child, "simpleType")) {
6563 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006564 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006565 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006566 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006567 */
6568 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6569 &repName, (xmlSchemaTypePtr) ret, node, child,
6570 "The attribute 'type' and the <simpleType> child "
6571 "are mutually exclusive", NULL);
6572 } else
6573 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6574 child = child->next;
6575 }
6576 if (child != NULL)
6577 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6578 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6579 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006580 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006581 /*
6582 * Cleanup.
6583 */
6584 if (repName != NULL)
6585 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006586 return (ret);
6587}
6588
6589/**
6590 * xmlSchemaParseAttributeGroup:
6591 * @ctxt: a schema validation context
6592 * @schema: the schema being built
6593 * @node: a subtree containing XML Schema informations
6594 *
6595 * parse a XML schema Attribute Group declaration
6596 * *WARNING* this interface is highly subject to change
6597 *
6598 * Returns the attribute group or NULL in case of error.
6599 */
6600static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006601xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006602 xmlSchemaPtr schema, xmlNodePtr node,
6603 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006604{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006605 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006606 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006607 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006608 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006609 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006610
6611 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6612 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006613
6614 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006615 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006616 if ((topLevel) || (attr == NULL)) {
6617 /*
6618 * Parse as an attribute group definition.
6619 * Note that those are allowed at top level only.
6620 */
6621 if (nameAttr == NULL) {
6622 xmlSchemaPMissingAttrErr(ctxt,
6623 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006624 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006625 return (NULL);
6626 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006627 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006628 * (xmlNodePtr) nameAttr);
6629 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006630 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006631 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006632 */
6633 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006634 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006635 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6636 return (NULL);
6637 }
6638 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6639 if (ret == NULL)
6640 return (NULL);
6641 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6642 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6643 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006644 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006645 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006646 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006647 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006648
6649 /*
6650 * Parse as an attribute group definition reference.
6651 */
6652 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006653 xmlSchemaPMissingAttrErr(ctxt,
6654 XML_SCHEMAP_S4S_ATTR_MISSING,
6655 NULL, node, "ref", NULL);
6656 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006657 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006658 NULL, NULL, attr, &refNs,&ref);
6659
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006660 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006661 name = (const xmlChar *) buf;
6662 if (name == NULL) {
6663 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6664 "attribute group definition reference", node);
6665 return (NULL);
6666 }
6667 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6668 if (ret == NULL)
6669 return (NULL);
6670 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6671 ret->ref = ref;
6672 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006673 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006674 xmlSchemaCheckReference(ctxt, schema, node,
6675 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006676 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006677 /*
6678 * Check for illegal attributes.
6679 */
6680 attr = node->properties;
6681 while (attr != NULL) {
6682 if (attr->ns == NULL) {
6683 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6684 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006685 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006686 {
6687 xmlSchemaPIllegalAttrErr(ctxt,
6688 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6689 NULL, NULL, attr);
6690 }
6691 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6692 xmlSchemaPIllegalAttrErr(ctxt,
6693 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6694 NULL, NULL, attr);
6695 }
6696 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006697 }
6698 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006699 /*
6700 * And now for the children...
6701 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006702 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006703 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006704 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006705 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006706 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006708 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006709 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006710 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006711 if (IS_SCHEMA(child, "anyAttribute")) {
6712 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6713 child = child->next;
6714 }
6715 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006716 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006717 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006718 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6719 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006720 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006721 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006722 ctxt->container = oldcontainer;
6723 return (ret);
6724}
6725
6726/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006727 * xmlSchemaPValAttrFormDefault:
6728 * @value: the value
6729 * @flags: the flags to be modified
6730 * @flagQualified: the specific flag for "qualified"
6731 *
6732 * Returns 0 if the value is valid, 1 otherwise.
6733 */
6734static int
6735xmlSchemaPValAttrFormDefault(const xmlChar *value,
6736 int *flags,
6737 int flagQualified)
6738{
6739 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6740 if ((*flags & flagQualified) == 0)
6741 *flags |= flagQualified;
6742 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006743 return (1);
6744
William M. Brack2f2a6632004-08-20 23:09:47 +00006745 return (0);
6746}
6747
6748/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006749 * xmlSchemaPValAttrBlockFinal:
6750 * @value: the value
6751 * @flags: the flags to be modified
6752 * @flagAll: the specific flag for "#all"
6753 * @flagExtension: the specific flag for "extension"
6754 * @flagRestriction: the specific flag for "restriction"
6755 * @flagSubstitution: the specific flag for "substitution"
6756 * @flagList: the specific flag for "list"
6757 * @flagUnion: the specific flag for "union"
6758 *
6759 * Validates the value of the attribute "final" and "block". The value
6760 * is converted into the specified flag values and returned in @flags.
6761 *
6762 * Returns 0 if the value is valid, 1 otherwise.
6763 */
6764
6765static int
6766xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006767 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006768 int flagAll,
6769 int flagExtension,
6770 int flagRestriction,
6771 int flagSubstitution,
6772 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006773 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006774{
6775 int ret = 0;
6776
6777 /*
6778 * TODO: This does not check for dublicate entries.
6779 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006780 if ((flags == NULL) || (value == NULL))
6781 return (-1);
6782 if (value[0] == 0)
6783 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006784 if (xmlStrEqual(value, BAD_CAST "#all")) {
6785 if (flagAll != -1)
6786 *flags |= flagAll;
6787 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006788 if (flagExtension != -1)
6789 *flags |= flagExtension;
6790 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006791 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006792 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006793 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006794 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006795 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006796 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006797 *flags |= flagUnion;
6798 }
6799 } else {
6800 const xmlChar *end, *cur = value;
6801 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006802
Daniel Veillardc0826a72004-08-10 14:17:33 +00006803 do {
6804 while (IS_BLANK_CH(*cur))
6805 cur++;
6806 end = cur;
6807 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6808 end++;
6809 if (end == cur)
6810 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006811 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006812 if (xmlStrEqual(item, BAD_CAST "extension")) {
6813 if (flagExtension != -1) {
6814 if ((*flags & flagExtension) == 0)
6815 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006816 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006817 ret = 1;
6818 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
6819 if (flagRestriction != -1) {
6820 if ((*flags & flagRestriction) == 0)
6821 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006822 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006823 ret = 1;
6824 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
6825 if (flagSubstitution != -1) {
6826 if ((*flags & flagSubstitution) == 0)
6827 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006828 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006829 ret = 1;
6830 } else if (xmlStrEqual(item, BAD_CAST "list")) {
6831 if (flagList != -1) {
6832 if ((*flags & flagList) == 0)
6833 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006834 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006835 ret = 1;
6836 } else if (xmlStrEqual(item, BAD_CAST "union")) {
6837 if (flagUnion != -1) {
6838 if ((*flags & flagUnion) == 0)
6839 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006840 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006841 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006842 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006843 ret = 1;
6844 if (item != NULL)
6845 xmlFree(item);
6846 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006847 } while ((ret == 0) && (*cur != 0));
6848 }
6849
Daniel Veillardc0826a72004-08-10 14:17:33 +00006850 return (ret);
6851}
6852
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006853static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006854xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006855 xmlSchemaIDCPtr idc,
6856 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006857 xmlAttrPtr attr,
6858 int isField)
6859{
6860 xmlNodePtr node;
6861
6862 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006863 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006864 * Schema Component Constraint: Selector Value OK
6865 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006866 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006867 * in [XPath].
6868 */
6869 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006870 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006871 XML_SCHEMAP_INTERNAL,
6872 "Internal error: xmlSchemaCheckCSelectorXPath, "
6873 "the selector is not specified.\n", NULL, NULL);
6874 return (-1);
6875 }
6876 if (attr == NULL)
6877 node = idc->node;
6878 else
6879 node = (xmlNodePtr) attr;
6880 if (selector->xpath == NULL) {
6881 xmlSchemaPCustomErr(ctxt,
6882 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006883 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6884 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006885 "The XPath expression of the selector is not valid", NULL);
6886 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
6887 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006888 const xmlChar **nsArray = NULL;
6889 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006890 /*
6891 * Compile the XPath expression.
6892 */
6893 /*
6894 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006895 * TODO: Call xmlPatterncompile with different options for selector/
6896 * field.
6897 */
6898 nsList = xmlGetNsList(attr->doc, attr->parent);
6899 /*
6900 * Build an array of prefixes and namespaces.
6901 */
6902 if (nsList != NULL) {
6903 int i, count = 0;
6904 xmlNsPtr ns;
6905
6906 for (i = 0; nsList[i] != NULL; i++)
6907 count++;
6908
6909 nsArray = (const xmlChar **) xmlMalloc(
6910 (count * 2 + 1) * sizeof(const xmlChar *));
6911 if (nsArray == NULL) {
6912 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
6913 NULL);
6914 return (-1);
6915 }
6916 for (i = 0; i < count; i++) {
6917 ns = nsList[i];
6918 nsArray[2 * i] = nsList[i]->href;
6919 nsArray[2 * i + 1] = nsList[i]->prefix;
6920 }
6921 nsArray[count * 2] = NULL;
6922 xmlFree(nsList);
6923 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006924 /*
6925 * TODO: Differentiate between "selector" and "field".
6926 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006927 if (isField)
6928 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006929 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006930 else
6931 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00006932 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00006933 if (nsArray != NULL)
6934 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006935
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006936 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006937 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00006938 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006939 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6940 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006941 "The XPath expression '%s' could not be "
6942 "compiled", selector->xpath);
6943 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006944 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006945 }
6946 return (0);
6947}
6948
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006949#define ADD_ANNOTATION(annot) \
6950 xmlSchemaAnnotPtr cur = item->annot; \
6951 if (item->annot == NULL) { \
6952 item->annot = annot; \
6953 return (annot); \
6954 } \
6955 cur = item->annot; \
6956 if (cur->next != NULL) { \
6957 cur = cur->next; \
6958 } \
6959 cur->next = annot;
6960
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006961/**
6962 * xmlSchemaAssignAnnotation:
6963 * @item: the schema component
6964 * @annot: the annotation
6965 *
6966 * Adds the annotation to the given schema component.
6967 *
6968 * Returns the given annotaion.
6969 */
6970static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006971xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
6972 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006973{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006974 if ((annItem == NULL) || (annot == NULL))
6975 return (NULL);
6976 switch (annItem->type) {
6977 case XML_SCHEMA_TYPE_ELEMENT: {
6978 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
6979 ADD_ANNOTATION(annot)
6980 }
6981 break;
6982 case XML_SCHEMA_TYPE_ATTRIBUTE: {
6983 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
6984 ADD_ANNOTATION(annot)
6985 }
6986 break;
6987 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
6988 case XML_SCHEMA_TYPE_ANY: {
6989 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
6990 ADD_ANNOTATION(annot)
6991 }
6992 break;
6993 case XML_SCHEMA_TYPE_PARTICLE:
6994 case XML_SCHEMA_TYPE_IDC_KEY:
6995 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006996 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006997 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
6998 ADD_ANNOTATION(annot)
6999 }
7000 break;
7001 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7002 xmlSchemaAttributeGroupPtr item =
7003 (xmlSchemaAttributeGroupPtr) annItem;
7004 ADD_ANNOTATION(annot)
7005 }
7006 break;
7007 case XML_SCHEMA_TYPE_NOTATION: {
7008 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7009 ADD_ANNOTATION(annot)
7010 }
7011 break;
7012 case XML_SCHEMA_FACET_MININCLUSIVE:
7013 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7014 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7015 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7016 case XML_SCHEMA_FACET_TOTALDIGITS:
7017 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7018 case XML_SCHEMA_FACET_PATTERN:
7019 case XML_SCHEMA_FACET_ENUMERATION:
7020 case XML_SCHEMA_FACET_WHITESPACE:
7021 case XML_SCHEMA_FACET_LENGTH:
7022 case XML_SCHEMA_FACET_MAXLENGTH:
7023 case XML_SCHEMA_FACET_MINLENGTH: {
7024 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7025 ADD_ANNOTATION(annot)
7026 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007027 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007028 case XML_SCHEMA_TYPE_SIMPLE:
7029 case XML_SCHEMA_TYPE_COMPLEX: {
7030 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7031 ADD_ANNOTATION(annot)
7032 }
7033 break;
7034 case XML_SCHEMA_TYPE_GROUP: {
7035 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7036 ADD_ANNOTATION(annot)
7037 }
7038 break;
7039 case XML_SCHEMA_TYPE_SEQUENCE:
7040 case XML_SCHEMA_TYPE_CHOICE:
7041 case XML_SCHEMA_TYPE_ALL: {
7042 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7043 ADD_ANNOTATION(annot)
7044 }
7045 break;
7046 default:
7047 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007048 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007049 NULL, NULL, NULL,
7050 "Internal error: xmlSchemaAddAnnotation, "
7051 "The item is not a annotated schema component", NULL);
7052 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007053 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007054 return (annot);
7055}
7056
7057/**
7058 * xmlSchemaParseIDCSelectorAndField:
7059 * @ctxt: a schema validation context
7060 * @schema: the schema being built
7061 * @node: a subtree containing XML Schema informations
7062 *
7063 * Parses a XML Schema identity-contraint definition's
7064 * <selector> and <field> elements.
7065 *
7066 * Returns the parsed identity-constraint definition.
7067 */
7068static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007069xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007070 xmlSchemaPtr schema,
7071 xmlSchemaIDCPtr idc,
7072 xmlNodePtr node,
7073 int isField)
7074{
7075 xmlSchemaIDCSelectPtr item;
7076 xmlNodePtr child = NULL;
7077 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007078
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007079 /*
7080 * Check for illegal attributes.
7081 */
7082 attr = node->properties;
7083 while (attr != NULL) {
7084 if (attr->ns == NULL) {
7085 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7086 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007087 xmlSchemaPIllegalAttrErr(ctxt,
7088 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7089 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007090 }
7091 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007092 xmlSchemaPIllegalAttrErr(ctxt,
7093 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7094 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007095 }
7096 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007097 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007098 /*
7099 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007100 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007101 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7102 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007103 xmlSchemaPErrMemory(ctxt,
7104 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007105 NULL);
7106 return (NULL);
7107 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007108 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007109 /*
7110 * Attribute "xpath" (mandatory).
7111 */
7112 attr = xmlSchemaGetPropNode(node, "xpath");
7113 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007114 xmlSchemaPMissingAttrErr(ctxt,
7115 XML_SCHEMAP_S4S_ATTR_MISSING,
7116 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007117 "name", NULL);
7118 } else {
7119 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7120 /*
7121 * URGENT TODO: "field"s have an other syntax than "selector"s.
7122 */
7123
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007124 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7125 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007126 xmlSchemaPErr(ctxt,
7127 (xmlNodePtr) attr,
7128 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007129 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007130 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007131 NULL, NULL);
7132 }
7133
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007134 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007135 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007136 /*
7137 * And now for the children...
7138 */
7139 child = node->children;
7140 if (IS_SCHEMA(child, "annotation")) {
7141 /*
7142 * Add the annotation to the parent IDC.
7143 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007144 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007145 xmlSchemaParseAnnotation(ctxt, schema, child));
7146 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007147 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007148 if (child != NULL) {
7149 xmlSchemaPContentErr(ctxt,
7150 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007151 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007152 NULL, "(annotation?)");
7153 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007154
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007155 return (item);
7156}
7157
7158/**
7159 * xmlSchemaParseIDC:
7160 * @ctxt: a schema validation context
7161 * @schema: the schema being built
7162 * @node: a subtree containing XML Schema informations
7163 *
7164 * Parses a XML Schema identity-contraint definition.
7165 *
7166 * Returns the parsed identity-constraint definition.
7167 */
7168static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007169xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007170 xmlSchemaPtr schema,
7171 xmlNodePtr node,
7172 xmlSchemaTypeType idcCategory,
7173 const xmlChar *targetNamespace)
7174{
7175 xmlSchemaIDCPtr item = NULL;
7176 xmlNodePtr child = NULL;
7177 xmlAttrPtr attr;
7178 const xmlChar *name = NULL;
7179 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7180 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007181
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007182 /*
7183 * Check for illegal attributes.
7184 */
7185 attr = node->properties;
7186 while (attr != NULL) {
7187 if (attr->ns == NULL) {
7188 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7189 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7190 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7191 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007192 xmlSchemaPIllegalAttrErr(ctxt,
7193 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7194 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007195 }
7196 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007197 xmlSchemaPIllegalAttrErr(ctxt,
7198 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7199 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007200 }
7201 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007202 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007203 /*
7204 * Attribute "name" (mandatory).
7205 */
7206 attr = xmlSchemaGetPropNode(node, "name");
7207 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007208 xmlSchemaPMissingAttrErr(ctxt,
7209 XML_SCHEMAP_S4S_ATTR_MISSING,
7210 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007211 "name", NULL);
7212 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007213 } else if (xmlSchemaPValAttrNode(ctxt,
7214 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007215 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7216 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007217 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007218 /*
7219 * Create the component.
7220 */
7221 if (schema->idcDef == NULL)
7222 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007223 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007224 return (NULL);
7225
7226 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7227 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007228 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007229 "allocating an identity-constraint definition", NULL);
7230 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007231 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007232 /*
7233 * Add the IDC to the list of IDCs on the schema component.
7234 */
7235 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007236 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007237 xmlSchemaPCustomErrExt(ctxt,
7238 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007239 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007240 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007241 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007242 name, targetNamespace, NULL);
7243 xmlFree(item);
7244 return (NULL);
7245 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007246 memset(item, 0, sizeof(xmlSchemaIDC));
7247 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007248 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007249 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007250 if (ctxt->assemble != NULL)
7251 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007252 /*
7253 * The target namespace of the parent element declaration.
7254 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007255 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007256 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7257 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007258 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7259 /*
7260 * Attribute "refer" (mandatory).
7261 */
7262 attr = xmlSchemaGetPropNode(node, "refer");
7263 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007264 xmlSchemaPMissingAttrErr(ctxt,
7265 XML_SCHEMAP_S4S_ATTR_MISSING,
7266 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007267 "refer", NULL);
7268 } else {
7269 /*
7270 * Create a reference item.
7271 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007272 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007273 NULL, NULL);
7274 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007275 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007276 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007277 NULL, NULL, attr,
7278 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007279 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007280 xmlSchemaCheckReference(ctxt, schema, node,
7281 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007282 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007283 }
7284 }
7285 /*
7286 * And now for the children...
7287 */
7288 child = node->children;
7289 if (IS_SCHEMA(child, "annotation")) {
7290 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7291 child = child->next;
7292 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007293 if (child == NULL) {
7294 xmlSchemaPContentErr(ctxt,
7295 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007296 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007297 "A child element is missing",
7298 "(annotation?, (selector, field+))");
7299 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007300 /*
7301 * Child element <selector>.
7302 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007303 if (IS_SCHEMA(child, "selector")) {
7304 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007305 item, child, 0);
7306 child = child->next;
7307 /*
7308 * Child elements <field>.
7309 */
7310 if (IS_SCHEMA(child, "field")) {
7311 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007312 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007313 item, child, 1);
7314 if (field != NULL) {
7315 field->index = item->nbFields;
7316 item->nbFields++;
7317 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007318 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007319 else
7320 item->fields = field;
7321 lastField = field;
7322 }
7323 child = child->next;
7324 } while (IS_SCHEMA(child, "field"));
7325 } else {
7326 xmlSchemaPContentErr(ctxt,
7327 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007328 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007329 NULL, "(annotation?, (selector, field+))");
7330 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007331 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007332 if (child != NULL) {
7333 xmlSchemaPContentErr(ctxt,
7334 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007335 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007336 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007337 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007338
7339 return (item);
7340}
7341
Daniel Veillardc0826a72004-08-10 14:17:33 +00007342/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007343 * xmlSchemaParseElement:
7344 * @ctxt: a schema validation context
7345 * @schema: the schema being built
7346 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007347 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007348 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007349 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007350 * *WARNING* this interface is highly subject to change
7351 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007352 * Returns the element declaration or a particle; NULL in case
7353 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007354 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007355static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007356xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007357 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007358{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007359 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007360 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007361 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007362 xmlNodePtr child = NULL;
7363 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007364 int min, max, isRef = 0;
7365 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007366
7367 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7368 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007369
Daniel Veillard4255d502002-04-16 15:50:10 +00007370 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007371 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007372 /*
7373 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007374 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007375 * robust.
7376 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007377 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007378 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007379 if ((topLevel) || (attr == NULL)) {
7380 if (nameAttr == NULL) {
7381 xmlSchemaPMissingAttrErr(ctxt,
7382 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007383 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007384 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007385 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007386 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007387 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007388
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007389 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007390 child = node->children;
7391 if (IS_SCHEMA(child, "annotation")) {
7392 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7393 child = child->next;
7394 }
7395 /*
7396 * Skip particle part if a global declaration.
7397 */
7398 if (topLevel)
7399 goto declaration_part;
7400 /*
7401 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007402 */
7403 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7404 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7405 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007406 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7407 if (particle == NULL)
7408 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007409
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007410 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7411
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007412 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007413 const xmlChar *refNs = NULL, *ref = NULL;
7414 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007415 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007416 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007417 */
7418 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007419 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007420 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007421 /*
7422 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007423 */
7424 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007425 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007426 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007427 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007428 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007429 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007430 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007431 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007432 attr = node->properties;
7433 while (attr != NULL) {
7434 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007435 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7436 xmlStrEqual(attr->name, BAD_CAST "name") ||
7437 xmlStrEqual(attr->name, BAD_CAST "id") ||
7438 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7439 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7440 {
7441 attr = attr->next;
7442 continue;
7443 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007444 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007445 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007446 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007447 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007448 "Only the attributes 'minOccurs', 'maxOccurs' and "
7449 "'id' are allowed in addition to 'ref'");
7450 break;
7451 }
7452 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7453 xmlSchemaPIllegalAttrErr(ctxt,
7454 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007455 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007456 }
7457 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007458 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007459 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007460 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007461 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007462 if (child != NULL) {
7463 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 NULL, NULL, node, child, NULL, "(annotation?)");
7465 }
7466 if ((min == 0) && (max == 0))
7467 goto return_null;
7468 /*
7469 * Create the reference item.
7470 */
7471 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7472 ref, refNs);
7473 if (refer == NULL)
7474 goto return_null;
7475 particle->children = (xmlSchemaTreeItemPtr) refer;
7476 particle->annot = annot;
7477 /*
7478 * Add to assembled items; the reference need to be resolved.
7479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007480 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007481 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7482
7483 return ((xmlSchemaBasicItemPtr) particle);
7484 }
7485 /*
7486 * The declaration part ===============================================
7487 */
7488declaration_part:
7489 {
7490 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7491 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7492
7493 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007494 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007495 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007496 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007497 * Evaluate the target namespace.
7498 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007499 if (topLevel) {
7500 ns = schema->targetNamespace;
7501 } else {
7502 attr = xmlSchemaGetPropNode(node, "form");
7503 if (attr != NULL) {
7504 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7505 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007506 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007507 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007508 xmlSchemaPSimpleTypeErr(ctxt,
7509 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7510 NULL, (xmlNodePtr) attr,
7511 NULL, "(qualified | unqualified)",
7512 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007513 }
7514 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007515 ns = schema->targetNamespace;
7516 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007517 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007518 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007519 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007520 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007521 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7522 decl->node = node;
7523 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007524 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007525 * Check for illegal attributes.
7526 */
William M. Bracke7091952004-05-11 15:09:58 +00007527 attr = node->properties;
7528 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007529 if (attr->ns == NULL) {
7530 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7531 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007532 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007533 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007534 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007535 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007536 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7537 {
7538 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007539 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007540 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007541 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007542 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007543 xmlSchemaPIllegalAttrErr(ctxt,
7544 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7545 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007546 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007547 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7548 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007549 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7550
7551 xmlSchemaPIllegalAttrErr(ctxt,
7552 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007553 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007554 }
7555 }
7556 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007557
Daniel Veillardc0826a72004-08-10 14:17:33 +00007558 xmlSchemaPIllegalAttrErr(ctxt,
7559 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007560 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007561 }
7562 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007563 }
William M. Bracke7091952004-05-11 15:09:58 +00007564 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007565 * Extract/validate attributes.
7566 */
7567 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007568 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007569 * Process top attributes of global element declarations here.
7570 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007571 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7572 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007573 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7574 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7575 &(decl->substGroupNs), &(decl->substGroup));
7576 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007577 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007578 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007579 /*
7580 * Attribute "final".
7581 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007582 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007583 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007584 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7585 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7586 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7587 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007588 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007589 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7590 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007591 -1,
7592 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7593 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007594 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007595 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007596 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7597 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007598 attrValue, NULL, NULL, NULL);
7599 }
7600 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007601 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007602 /*
7603 * Attribute "block".
7604 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007605 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007606 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007607 /*
7608 * Apply default "block" values.
7609 */
7610 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7611 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7612 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7613 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7614 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7615 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007616 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007617 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7618 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007619 -1,
7620 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007621 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007622 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7623 xmlSchemaPSimpleTypeErr(ctxt,
7624 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007625 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007626 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007627 "restriction | substitution))", attrValue,
7628 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007629 }
7630 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007631 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007632 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007633 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007634
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007635 attr = xmlSchemaGetPropNode(node, "type");
7636 if (attr != NULL) {
7637 xmlSchemaPValAttrNodeQName(ctxt, schema,
7638 NULL, (xmlSchemaTypePtr) decl, attr,
7639 &(decl->namedTypeNs), &(decl->namedType));
7640 xmlSchemaCheckReference(ctxt, schema, node,
7641 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7642 }
7643 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7644 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007645 if (attr != NULL) {
7646 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007647 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007648 /*
7649 * 3.3.3 : 1
7650 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007651 */
7652 xmlSchemaPMutualExclAttrErr(ctxt,
7653 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007654 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007655 "default", "fixed");
7656 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007657 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7658 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007659 }
William M. Bracke7091952004-05-11 15:09:58 +00007660 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007661 /*
7662 * And now for the children...
7663 */
7664 oldcontainer = ctxt->container;
7665 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007666 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007667 /*
7668 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007669 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007670 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007671 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007672 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007673 xmlSchemaPContentErr(ctxt,
7674 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007675 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007676 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007677 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007678 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007679 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007680 child = child->next;
7681 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007682 /*
7683 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007684 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007685 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007686 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007687 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 xmlSchemaPContentErr(ctxt,
7689 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007690 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007691 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007692 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007693 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007694 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007695 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007696 }
William M. Bracke7091952004-05-11 15:09:58 +00007697 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007698 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007699 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007700 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007701 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007702 } else if (IS_SCHEMA(child, "key")) {
7703 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007704 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007705 } else if (IS_SCHEMA(child, "keyref")) {
7706 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007707 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007708 }
7709 if (lastIDC != NULL)
7710 lastIDC->next = curIDC;
7711 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007712 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007713 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007714 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007715 }
7716 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007717 xmlSchemaPContentErr(ctxt,
7718 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007719 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007720 NULL, "(annotation?, ((simpleType | complexType)?, "
7721 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007722 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007723 ctxt->container = oldcontainer;
7724 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007725 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007726 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007727 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007728 * different layer.
7729 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007730 FREE_AND_NULL(des)
7731 if (topLevel)
7732 return ((xmlSchemaBasicItemPtr) decl);
7733 else {
7734 particle->children = (xmlSchemaTreeItemPtr) decl;
7735 return ((xmlSchemaBasicItemPtr) particle);
7736 }
7737
7738return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007739 FREE_AND_NULL(des);
7740 if (annot != NULL) {
7741 if (particle != NULL)
7742 particle->annot = NULL;
7743 if (decl != NULL)
7744 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007745 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007746 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007747 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007748}
7749
7750/**
7751 * xmlSchemaParseUnion:
7752 * @ctxt: a schema validation context
7753 * @schema: the schema being built
7754 * @node: a subtree containing XML Schema informations
7755 *
7756 * parse a XML schema Union definition
7757 * *WARNING* this interface is highly subject to change
7758 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007759 * Returns -1 in case of internal error, 0 in case of success and a positive
7760 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00007761 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007762static int
Daniel Veillard4255d502002-04-16 15:50:10 +00007763xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007764 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007766 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007767 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007768 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007769 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00007770
7771 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007772 return (-1);
7773 /* Not a component, don't create it. */
7774 type = ctxt->ctxtType;
7775 /*
7776 * Mark the simple type as being of variety "union".
7777 */
7778 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007779 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007780 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7781 * then the ·simple ur-type definition·."
7782 */
7783 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007784 /*
7785 * Check for illegal attributes.
7786 */
7787 attr = node->properties;
7788 while (attr != NULL) {
7789 if (attr->ns == NULL) {
7790 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7791 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007792 xmlSchemaPIllegalAttrErr(ctxt,
7793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7794 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007795 }
7796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007797 xmlSchemaPIllegalAttrErr(ctxt,
7798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7799 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007800 }
7801 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007802 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00007803 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00007804 /*
7805 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007806 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00007807 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007808 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007809 if (attr != NULL) {
7810 const xmlChar *end;
7811 xmlChar *tmp;
7812 const xmlChar *localName, *nsName;
7813 xmlSchemaTypeLinkPtr link, lastLink = NULL;
7814 xmlSchemaQNameRefPtr ref;
7815
7816 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007817 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007818 do {
7819 while (IS_BLANK_CH(*cur))
7820 cur++;
7821 end = cur;
7822 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7823 end++;
7824 if (end == cur)
7825 break;
7826 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007827 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
7828 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007829 /*
7830 * Create the member type link.
7831 */
7832 link = (xmlSchemaTypeLinkPtr)
7833 xmlMalloc(sizeof(xmlSchemaTypeLink));
7834 if (link == NULL) {
7835 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
7836 "allocating a type link", NULL);
7837 return (-1);
7838 }
7839 link->type = NULL;
7840 link->next = NULL;
7841 if (lastLink == NULL)
7842 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007843 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007844 lastLink->next = link;
7845 lastLink = link;
7846 /*
7847 * Create a reference item.
7848 */
7849 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
7850 localName, nsName);
7851 if (ref == NULL) {
7852 FREE_AND_NULL(tmp)
7853 return (-1);
7854 }
7855 /*
7856 * Assign the reference to the link, it will be resolved
7857 * later during fixup of the union simple type.
7858 */
7859 link->type = (xmlSchemaTypePtr) ref;
7860 }
7861 FREE_AND_NULL(tmp)
7862 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007863 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007864
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007865 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007866 /*
7867 * And now for the children...
7868 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007869 child = node->children;
7870 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007871 /*
7872 * Add the annotation to the simple type ancestor.
7873 */
7874 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7875 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007876 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007877 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007878 if (IS_SCHEMA(child, "simpleType")) {
7879 xmlSchemaTypePtr subtype, last = NULL;
7880
7881 /*
7882 * Anchor the member types in the "subtypes" field of the
7883 * simple type.
7884 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007885 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007886 subtype = (xmlSchemaTypePtr)
7887 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
7888 if (subtype != NULL) {
7889 if (last == NULL) {
7890 type->subtypes = subtype;
7891 last = subtype;
7892 } else {
7893 last->next = subtype;
7894 last = subtype;
7895 }
7896 last->next = NULL;
7897 }
7898 child = child->next;
7899 }
Daniel Veillard4255d502002-04-16 15:50:10 +00007900 }
7901 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007902 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007903 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007904 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007905 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007906 if ((attr == NULL) && (type->subtypes == NULL)) {
7907 /*
7908 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007909 * Either the memberTypes [attribute] of the <union> element must
7910 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007911 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007912 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007913 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
7914 NULL, NULL, node,
7915 "Either the attribute 'memberTypes' or "
7916 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007917 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007918 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00007919}
7920
7921/**
7922 * xmlSchemaParseList:
7923 * @ctxt: a schema validation context
7924 * @schema: the schema being built
7925 * @node: a subtree containing XML Schema informations
7926 *
7927 * parse a XML schema List definition
7928 * *WARNING* this interface is highly subject to change
7929 *
William M. Bracke7091952004-05-11 15:09:58 +00007930 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007931 * 1 in case of success.
7932 */
7933static xmlSchemaTypePtr
7934xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007935 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007936{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007937 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00007938 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007939 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00007940
7941 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7942 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007943 /* Not a component, don't create it. */
7944 type = ctxt->ctxtType;
7945 /*
7946 * Mark the type as being of variety "list".
7947 */
7948 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007949 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007950 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
7951 * then the ·simple ur-type definition·."
7952 */
7953 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00007954 /*
7955 * Check for illegal attributes.
7956 */
7957 attr = node->properties;
7958 while (attr != NULL) {
7959 if (attr->ns == NULL) {
7960 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7961 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007962 xmlSchemaPIllegalAttrErr(ctxt,
7963 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7964 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007965 }
7966 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007967 xmlSchemaPIllegalAttrErr(ctxt,
7968 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7969 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00007970 }
7971 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007972 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007973
7974 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
7975
William M. Brack2f2a6632004-08-20 23:09:47 +00007976 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007977 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
7978 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00007979 */
7980 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007981 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00007982 /*
7983 * And now for the children...
7984 */
Daniel Veillard4255d502002-04-16 15:50:10 +00007985 child = node->children;
7986 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
7988 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007989 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007990 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007991 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007992 /*
7993 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007994 * Either the itemType [attribute] or the <simpleType> [child] of
7995 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007996 */
7997 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007998 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00007999 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008000 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008001 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008002 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008003 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008004 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008005 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008006 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008007 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008008 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008009 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008010 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008011 "Either the attribute 'itemType' or the <simpleType> child "
8012 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008013 }
8014 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008015 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008016 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008017 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008018 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008019 if ((type->ref == NULL) &&
8020 (type->subtypes == NULL) &&
8021 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008022 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008023 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008024 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008025 "Either the attribute 'itemType' or the <simpleType> child "
8026 "must be present", NULL);
8027 }
8028 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008029}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008030
Daniel Veillard4255d502002-04-16 15:50:10 +00008031/**
8032 * xmlSchemaParseSimpleType:
8033 * @ctxt: a schema validation context
8034 * @schema: the schema being built
8035 * @node: a subtree containing XML Schema informations
8036 *
8037 * parse a XML schema Simple Type definition
8038 * *WARNING* this interface is highly subject to change
8039 *
William M. Bracke7091952004-05-11 15:09:58 +00008040 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008041 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008042 */
8043static xmlSchemaTypePtr
8044xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008045 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008046{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008047 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008048 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008049 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008050 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008051
8052 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8053 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008054
Daniel Veillardc0826a72004-08-10 14:17:33 +00008055 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008056 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008057 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008058 xmlSchemaPMissingAttrErr(ctxt,
8059 XML_SCHEMAP_S4S_ATTR_MISSING,
8060 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008061 "name", NULL);
8062 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008063 } else {
8064 if (xmlSchemaPValAttrNode(ctxt,
8065 NULL, NULL, attr,
8066 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8067 return (NULL);
8068 /*
8069 * Skip built-in types.
8070 */
8071 if (ctxt->isS4S) {
8072 xmlSchemaTypePtr biType;
8073
8074 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8075 if (biType != NULL)
8076 return (biType);
8077 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008078 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008079 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008080
Daniel Veillardc0826a72004-08-10 14:17:33 +00008081 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008082 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008083
Daniel Veillard01fa6152004-06-29 17:04:39 +00008084 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008085 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008086 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008087 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008088 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008089 if (type == NULL)
8090 return (NULL);
8091 type->node = node;
8092 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008093 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008094 /*
8095 * Check for illegal attributes.
8096 */
8097 attr = node->properties;
8098 while (attr != NULL) {
8099 if (attr->ns == NULL) {
8100 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008101 xmlSchemaPIllegalAttrErr(ctxt,
8102 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8103 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008104 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008105 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008106 xmlSchemaPIllegalAttrErr(ctxt,
8107 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8108 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008109 }
8110 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008111 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008112 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008113 /*
8114 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008115 *
8116 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008117 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008118 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008119 if (type == NULL)
8120 return (NULL);
8121 type->node = node;
8122 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008123 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008124 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8125 /*
8126 * Check for illegal attributes.
8127 */
8128 attr = node->properties;
8129 while (attr != NULL) {
8130 if (attr->ns == NULL) {
8131 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8132 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008133 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008134 xmlSchemaPIllegalAttrErr(ctxt,
8135 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8136 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008137 }
8138 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008139 xmlSchemaPIllegalAttrErr(ctxt,
8140 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8141 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008142 }
8143 attr = attr->next;
8144 }
8145 /*
8146 * Attribute "final".
8147 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008148 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008149 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008150 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8151 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8152 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8153 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8154 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8155 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008156 } else {
8157 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008158 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8159 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008160 XML_SCHEMAS_TYPE_FINAL_LIST,
8161 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8162
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008163 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008164 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008165 type, (xmlNodePtr) attr,
8166 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008167 attrValue, NULL, NULL, NULL);
8168 }
8169 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008170 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008171 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008172 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008173 /*
8174 * And now for the children...
8175 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008176 oldCtxtType = ctxt->ctxtType;
8177 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008178 ctxt->ctxtType = type;
8179 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008180 child = node->children;
8181 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008182 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8183 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008184 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008185 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008186 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8187 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008188 "(annotation?, (restriction | list | union))");
8189 } else if (IS_SCHEMA(child, "restriction")) {
8190 xmlSchemaParseRestriction(ctxt, schema, child,
8191 XML_SCHEMA_TYPE_SIMPLE);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008192 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008193 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008194 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008195 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008196 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008197 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008198 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008199 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008200 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008201 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8202 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008203 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008204 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008205 ctxt->parentItem = oldParentItem;
8206 ctxt->ctxtType = oldCtxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008207
Daniel Veillard4255d502002-04-16 15:50:10 +00008208 return (type);
8209}
8210
Daniel Veillard4255d502002-04-16 15:50:10 +00008211/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008212 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008213 * @ctxt: a schema validation context
8214 * @schema: the schema being built
8215 * @node: a subtree containing XML Schema informations
8216 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008217 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008218 * *WARNING* this interface is highly subject to change
8219 *
William M. Bracke7091952004-05-11 15:09:58 +00008220 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008221 * 1 in case of success.
8222 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008223static xmlSchemaTreeItemPtr
8224xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8225 xmlSchemaPtr schema,
8226 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008227{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008228 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008229 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008230 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008231 const xmlChar *ref = NULL, *refNs = NULL;
8232 int min, max;
8233
8234 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008235 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008236
8237 attr = xmlSchemaGetPropNode(node, "ref");
8238 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008239 xmlSchemaPMissingAttrErr(ctxt,
8240 XML_SCHEMAP_S4S_ATTR_MISSING,
8241 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008242 "ref", NULL);
8243 return (NULL);
8244 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008245 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008246 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008247 }
8248 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008249 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008250 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008251 /*
8252 * Check for illegal attributes.
8253 */
8254 attr = node->properties;
8255 while (attr != NULL) {
8256 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008257 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008258 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8259 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8260 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008261 xmlSchemaPIllegalAttrErr(ctxt,
8262 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8263 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008264 }
8265 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008266 xmlSchemaPIllegalAttrErr(ctxt,
8267 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8268 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008269 }
8270 attr = attr->next;
8271 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008272 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008273 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8274 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008275 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008276 /*
8277 * Create a reference item as the term; it will be substituted for
8278 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008279 */
8280 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008281 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8282 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8283 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8284 /*
8285 * And now for the children...
8286 */
8287 child = node->children;
8288 /* TODO: Is annotation even allowed for a model group reference? */
8289 if (IS_SCHEMA(child, "annotation")) {
8290 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008291 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008292 */
8293 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8294 child = child->next;
8295 }
8296 if (child != NULL) {
8297 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008298 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008299 NULL, NULL, node, child, NULL,
8300 "(annotation?)");
8301 }
8302 /*
8303 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8304 */
8305 if ((min == 0) && (max == 0))
8306 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008307 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008308 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8309 return ((xmlSchemaTreeItemPtr) item);
8310}
8311
8312/**
8313 * xmlSchemaParseModelGroupDefinition:
8314 * @ctxt: a schema validation context
8315 * @schema: the schema being built
8316 * @node: a subtree containing XML Schema informations
8317 *
8318 * Parses a XML schema model group definition.
8319 * *WARNING* this interface is highly subject to change
8320 *
8321 * Returns -1 in case of error, 0 if the declaration is improper and
8322 * 1 in case of success.
8323 */
8324static xmlSchemaModelGroupDefPtr
8325xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8326 xmlSchemaPtr schema,
8327 xmlNodePtr node)
8328{
8329 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008330 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008331 xmlAttrPtr attr;
8332 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008333
8334 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008335 return (NULL);
8336
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008337 attr = xmlSchemaGetPropNode(node, "name");
8338 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008339 xmlSchemaPMissingAttrErr(ctxt,
8340 XML_SCHEMAP_S4S_ATTR_MISSING,
8341 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008342 "name", NULL);
8343 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008344 } else if (xmlSchemaPValAttrNode(ctxt,
8345 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008346 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8347 return (NULL);
8348 }
8349 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8350 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008351 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008352 /*
8353 * Check for illegal attributes.
8354 */
8355 attr = node->properties;
8356 while (attr != NULL) {
8357 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008358 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008359 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008360 xmlSchemaPIllegalAttrErr(ctxt,
8361 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8362 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008363 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008364 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008365 xmlSchemaPIllegalAttrErr(ctxt,
8366 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8367 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008368 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008369 attr = attr->next;
8370 }
8371 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8372 /*
8373 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008374 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008375 child = node->children;
8376 if (IS_SCHEMA(child, "annotation")) {
8377 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8378 child = child->next;
8379 }
8380 if (IS_SCHEMA(child, "all")) {
8381 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8382 XML_SCHEMA_TYPE_ALL, 0);
8383 child = child->next;
8384 } else if (IS_SCHEMA(child, "choice")) {
8385 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8386 XML_SCHEMA_TYPE_CHOICE, 0);
8387 child = child->next;
8388 } else if (IS_SCHEMA(child, "sequence")) {
8389 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8390 XML_SCHEMA_TYPE_SEQUENCE, 0);
8391 child = child->next;
8392 }
8393 if (child != NULL) {
8394 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008395 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8396 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008397 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008398 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008399
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008400 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008401}
8402
8403/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008404 * xmlSchemaCleanupDoc:
8405 * @ctxt: a schema validation context
8406 * @node: the root of the document.
8407 *
8408 * removes unwanted nodes in a schemas document tree
8409 */
8410static void
8411xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8412{
8413 xmlNodePtr delete, cur;
8414
8415 if ((ctxt == NULL) || (root == NULL)) return;
8416
8417 /*
8418 * Remove all the blank text nodes
8419 */
8420 delete = NULL;
8421 cur = root;
8422 while (cur != NULL) {
8423 if (delete != NULL) {
8424 xmlUnlinkNode(delete);
8425 xmlFreeNode(delete);
8426 delete = NULL;
8427 }
8428 if (cur->type == XML_TEXT_NODE) {
8429 if (IS_BLANK_NODE(cur)) {
8430 if (xmlNodeGetSpacePreserve(cur) != 1) {
8431 delete = cur;
8432 }
8433 }
8434 } else if ((cur->type != XML_ELEMENT_NODE) &&
8435 (cur->type != XML_CDATA_SECTION_NODE)) {
8436 delete = cur;
8437 goto skip_children;
8438 }
8439
8440 /*
8441 * Skip to next node
8442 */
8443 if (cur->children != NULL) {
8444 if ((cur->children->type != XML_ENTITY_DECL) &&
8445 (cur->children->type != XML_ENTITY_REF_NODE) &&
8446 (cur->children->type != XML_ENTITY_NODE)) {
8447 cur = cur->children;
8448 continue;
8449 }
8450 }
8451 skip_children:
8452 if (cur->next != NULL) {
8453 cur = cur->next;
8454 continue;
8455 }
8456
8457 do {
8458 cur = cur->parent;
8459 if (cur == NULL)
8460 break;
8461 if (cur == root) {
8462 cur = NULL;
8463 break;
8464 }
8465 if (cur->next != NULL) {
8466 cur = cur->next;
8467 break;
8468 }
8469 } while (cur != NULL);
8470 }
8471 if (delete != NULL) {
8472 xmlUnlinkNode(delete);
8473 xmlFreeNode(delete);
8474 delete = NULL;
8475 }
8476}
8477
William M. Brack2f2a6632004-08-20 23:09:47 +00008478
8479/**
8480 * xmlSchemaImportSchema
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008481 *
William M. Brack2f2a6632004-08-20 23:09:47 +00008482 * @ctxt: a schema validation context
8483 * @schemaLocation: an URI defining where to find the imported schema
8484 *
8485 * import a XML schema
8486 * *WARNING* this interface is highly subject to change
8487 *
8488 * Returns -1 in case of error and 1 in case of success.
8489 */
8490#if 0
8491static xmlSchemaImportPtr
8492xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
8493 const xmlChar *schemaLocation)
8494{
8495 xmlSchemaImportPtr import;
8496 xmlSchemaParserCtxtPtr newctxt;
8497
8498 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8499 if (newctxt == NULL) {
8500 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
8501 NULL);
8502 return (NULL);
8503 }
8504 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
8505 /* Keep the same dictionnary for parsing, really */
8506 xmlDictReference(ctxt->dict);
8507 newctxt->dict = ctxt->dict;
8508 newctxt->includes = 0;
8509 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
8510
8511 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
8512 ctxt->userData);
8513
8514 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8515 if (import == NULL) {
8516 xmlSchemaPErrMemory(NULL, "allocating imported schema",
8517 NULL);
8518 xmlSchemaFreeParserCtxt(newctxt);
8519 return (NULL);
8520 }
8521
8522 memset(import, 0, sizeof(xmlSchemaImport));
8523 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8524 import->schema = xmlSchemaParse(newctxt);
8525
8526 if (import->schema == NULL) {
8527 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00008528 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008529 "Failed to import schema from location \"%s\".\n",
8530 schemaLocation, NULL);
8531
8532 xmlSchemaFreeParserCtxt(newctxt);
8533 /* The schemaLocation is held by the dictionary.
8534 if (import->schemaLocation != NULL)
8535 xmlFree((xmlChar *)import->schemaLocation);
8536 */
8537 xmlFree(import);
8538 return NULL;
8539 }
8540
8541 xmlSchemaFreeParserCtxt(newctxt);
8542 return import;
8543}
8544#endif
8545
8546static void
8547xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8548{
8549 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8550 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8551
8552 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8553 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8554
8555 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8556 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8557 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8558 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8559 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8560 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8561 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8562 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8563
8564 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8565 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8566 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8567 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8568 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8569 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8570}
8571
8572static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008573xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008574 xmlSchemaPtr schema,
8575 xmlNodePtr node)
8576{
8577 xmlAttrPtr attr;
8578 const xmlChar *val;
8579
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008580 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8581 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008582 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008583 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8584 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008585 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008586 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8587
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008588 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008589 if (attr != NULL) {
8590 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008591 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008592 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008593 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008594 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008595 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008596 "(qualified | unqualified)", val, NULL, NULL, NULL);
8597 }
8598 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008599
8600 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008601 if (attr != NULL) {
8602 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008603 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008604 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008606 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008607 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008608 "(qualified | unqualified)", val, NULL, NULL, NULL);
8609 }
8610 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008611
8612 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008613 if (attr != NULL) {
8614 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8615 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8616 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8617 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8618 -1,
8619 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8620 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8621 xmlSchemaPSimpleTypeErr(ctxt,
8622 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008623 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008624 "(#all | List of (extension | restriction | list | union))",
8625 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008626 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008627 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008628
8629 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008630 if (attr != NULL) {
8631 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8632 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8633 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8634 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8635 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8636 xmlSchemaPSimpleTypeErr(ctxt,
8637 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008638 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008639 "(#all | List of (extension | restriction | substitution))",
8640 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008641 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008642 }
8643}
8644
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008645/**
8646 * xmlSchemaParseSchemaTopLevel:
8647 * @ctxt: a schema validation context
8648 * @schema: the schemas
8649 * @nodes: the list of top level nodes
8650 *
8651 * Returns the internal XML Schema structure built from the resource or
8652 * NULL in case of error
8653 */
8654static void
8655xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8656 xmlSchemaPtr schema, xmlNodePtr nodes)
8657{
8658 xmlNodePtr child;
8659 xmlSchemaAnnotPtr annot;
8660
8661 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8662 return;
8663
8664 child = nodes;
8665 while ((IS_SCHEMA(child, "include")) ||
8666 (IS_SCHEMA(child, "import")) ||
8667 (IS_SCHEMA(child, "redefine")) ||
8668 (IS_SCHEMA(child, "annotation"))) {
8669 if (IS_SCHEMA(child, "annotation")) {
8670 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8671 if (schema->annot == NULL)
8672 schema->annot = annot;
8673 else
8674 xmlSchemaFreeAnnot(annot);
8675 } else if (IS_SCHEMA(child, "import")) {
8676 xmlSchemaParseImport(ctxt, schema, child);
8677 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008678 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008679 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008680 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008681 } else if (IS_SCHEMA(child, "redefine")) {
8682 TODO
8683 }
8684 child = child->next;
8685 }
8686 while (child != NULL) {
8687 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008688 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008689 child = child->next;
8690 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008691 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008692 child = child->next;
8693 } else if (IS_SCHEMA(child, "element")) {
8694 xmlSchemaParseElement(ctxt, schema, child, 1);
8695 child = child->next;
8696 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008697 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008698 child = child->next;
8699 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008700 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008701 child = child->next;
8702 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008703 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008704 child = child->next;
8705 } else if (IS_SCHEMA(child, "notation")) {
8706 xmlSchemaParseNotation(ctxt, schema, child);
8707 child = child->next;
8708 } else {
8709 xmlSchemaPErr2(ctxt, NULL, child,
8710 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008711 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008712 child->name, NULL);
8713 child = child->next;
8714 }
8715 while (IS_SCHEMA(child, "annotation")) {
8716 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8717 if (schema->annot == NULL)
8718 schema->annot = annot;
8719 else
8720 xmlSchemaFreeAnnot(annot);
8721 child = child->next;
8722 }
8723 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008724 ctxt->parentItem = NULL;
8725 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008726}
8727
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008728static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008729xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008730 xmlHashTablePtr *imports,
8731 const xmlChar *nsName)
8732{
8733 xmlSchemaImportPtr ret;
8734
8735 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008736 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008737 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008738 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008739 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8740 NULL, NULL, (xmlNodePtr) ctxt->doc,
8741 "Internal error: failed to build the import table",
8742 NULL);
8743 return (NULL);
8744 }
8745 }
8746 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8747 if (ret == NULL) {
8748 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8749 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008750 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008751 memset(ret, 0, sizeof(xmlSchemaImport));
8752 if (nsName == NULL)
8753 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008754 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008755
8756 return (ret);
8757}
8758
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008759/**
8760 * xmlSchemaNewParserCtxtUseDict:
8761 * @URL: the location of the schema
8762 * @dict: the dictionary to be used
8763 *
8764 * Create an XML Schemas parse context for that file/resource expected
8765 * to contain an XML Schemas file.
8766 *
8767 * Returns the parser context or NULL in case of error
8768 */
8769static xmlSchemaParserCtxtPtr
8770xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
8771{
8772 xmlSchemaParserCtxtPtr ret;
8773 /*
8774 if (URL == NULL)
8775 return (NULL);
8776 */
8777
8778 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8779 if (ret == NULL) {
8780 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8781 NULL);
8782 return (NULL);
8783 }
8784 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
8785 ret->dict = dict;
8786 xmlDictReference(dict);
8787 if (URL != NULL)
8788 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
8789 ret->includes = 0;
8790 return (ret);
8791}
8792
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008793static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008794xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
8795{
8796 if (vctxt->pctxt == NULL) {
8797 if (vctxt->schema != NULL)
8798 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
8799 else
8800 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
8801 if (vctxt->pctxt == NULL) {
8802 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
8803 "failed to create a temp. parser context");
8804 return (-1);
8805 }
8806 /* TODO: Pass user data. */
8807 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
8808 }
8809 return (0);
8810}
8811
8812static int
8813xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008814 xmlSchemaPtr schema,
8815 xmlNodePtr node,
8816 const xmlChar *nsName,
8817 const xmlChar *location,
8818 xmlDocPtr *doc,
8819 const xmlChar **targetNamespace,
8820 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008821{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008822 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008823 xmlParserCtxtPtr parserCtxt;
8824 xmlSchemaImportPtr import;
8825 const xmlChar *ns;
8826 xmlNodePtr root;
8827
8828 /*
8829 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
8830 * <xsi:noNamespaceSchemaLocation>.
8831 */
8832 *doc = NULL;
8833 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008834 * Given that the schemaLocation [attribute] is only a hint, it is open
8835 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008836 * namespace, regardless of the ·actual value· of schemaLocation, but
8837 * such a strategy risks missing useful information when new
8838 * schemaLocations are offered.
8839 *
8840 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
8841 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
8842 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008843 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008844 */
8845 if (location == NULL) {
8846 /*
8847 * Schema Document Location Strategy:
8848 *
8849 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008850 * either as a resource which is an XML document or a <schema> element
8851 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008852 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008853 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008854 *
8855 * NOTE: Those stategies are not supported, so we will skip.
8856 */
8857 return (0);
8858 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008859 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008860 ns = XML_SCHEMAS_NO_NAMESPACE;
8861 else
8862 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008863
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008864 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008865 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008866 /*
8867 * There was a valid resource for the specified namespace already
8868 * defined, so skip.
8869 * TODO: This might be changed someday to allow import of
8870 * components from multiple documents for a single target namespace.
8871 */
8872 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008873 }
8874 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
8875 pctxt = (xmlSchemaParserCtxtPtr) actxt;
8876 else {
8877 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
8878 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
8879 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008880 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008881 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008882 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008883 * 2 Based on the location URI, identify an existing schema document,
8884 * either as a resource which is an XML document or a <schema> element
8885 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008886 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008887 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008888 * web which is or contains or references a <schema> element;
8889 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
8890 *
8891 */
8892 if ((absolute == 0) && (node != NULL)) {
8893 xmlChar *base, *URI;
8894
8895 base = xmlNodeGetBase(node->doc, node);
8896 if (base == NULL) {
8897 URI = xmlBuildURI(location, node->doc->URL);
8898 } else {
8899 URI = xmlBuildURI(location, base);
8900 xmlFree(base);
8901 }
8902 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008903 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008904 xmlFree(URI);
8905 }
8906 }
8907 parserCtxt = xmlNewParserCtxt();
8908 if (parserCtxt == NULL) {
8909 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
8910 "allocating a parser context", NULL);
8911 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008912 }
8913 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008914 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008915 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00008916 xmlDictReference(parserCtxt->dict);
8917 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008918 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008919 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008920 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008921 * 2.1 The referent is (a fragment of) a resource which is an
8922 * XML document (see clause 1.1), which in turn corresponds to
8923 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008924 * set, which in turn corresponds to a valid schema.
8925 * TODO: What to do with the "fragment" stuff?
8926 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008927 * 2.2 The referent is a <schema> element information item in
8928 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008929 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008930 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008931 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008932 */
8933 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008934 xmlErrorPtr lerr;
8935 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008936 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008937 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008938 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008939 * If the doc is NULL and the parser error is an IO error we
8940 * will assume that the resource could not be located or accessed.
8941 *
8942 * TODO: Try to find specific error codes to react only on
8943 * localisation failures.
8944 *
8945 * TODO, FIXME: Check the spec: is a namespace added to the imported
8946 * namespaces, even if the schemaLocation did not provide
8947 * a resource? I guess so, since omitting the "schemaLocation"
8948 * attribute, imports a namespace as well.
8949 */
8950 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008951 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008952 xmlFreeParserCtxt(parserCtxt);
8953 return(0);
8954 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008955 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008956 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008957 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008958 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008959 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008960 xmlFreeParserCtxt(parserCtxt);
8961 return(XML_SCHEMAP_SRC_IMPORT_2_1);
8962 }
8963 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008964
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008965 root = xmlDocGetRootElement(*doc);
8966 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008967 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008968 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008969 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008970 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008971 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008972 xmlFreeDoc(*doc);
8973 *doc = NULL;
8974 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008975 }
8976
8977 xmlSchemaCleanupDoc(pctxt, root);
8978
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008979 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008980 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008981 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008982 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008983 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008984 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008985 xmlFreeDoc(*doc);
8986 *doc = NULL;
8987 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008988 }
8989 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008990 /*
8991 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008992 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008993 if (nsName == NULL) {
8994 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008995 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008996 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008997 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008998 "The XML schema to be imported is not expected "
8999 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009000 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009001 xmlFreeDoc(*doc);
9002 *doc = NULL;
9003 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9004 }
9005 } else {
9006 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009007 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009008 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009009 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009010 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009011 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009012 xmlFreeDoc(*doc);
9013 *doc = NULL;
9014 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9015 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009016 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009017 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009018 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009019 "The XML schema to be imported is expected to have a "
9020 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009021 "its target namespace of '%s'",
9022 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009023 xmlFreeDoc(*doc);
9024 *doc = NULL;
9025 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9026 }
9027 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009028 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009029 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009030 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9031 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009032 xmlFreeDoc(*doc);
9033 *doc = NULL;
9034 return (-1);
9035 }
9036 import->schemaLocation = location;
9037 import->doc = *doc;
9038 return (0);
9039}
William M. Brack2f2a6632004-08-20 23:09:47 +00009040
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009041static void
9042xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9043 xmlSchemaPtr schema,
9044 const xmlChar *targetNamespace,
9045 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009046{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009047 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009048 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009049
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009050 /*
9051 * Save and reset the context & schema.
9052 */
9053 oldURL = pctxt->URL;
9054 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009055 pctxt->URL = node->doc->URL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009056 oldLocImps = pctxt->localImports;
9057 pctxt->localImports = NULL;
9058 oldNumLocImps = pctxt->nbLocalImports;
9059 pctxt->nbLocalImports = 0;
9060 oldSizeLocImps = pctxt->sizeLocalImports;
9061 pctxt->sizeLocalImports = 0;
9062 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009063 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009064 xmlSchemaClearSchemaDefaults(schema);
9065 oldTNS = schema->targetNamespace;
9066 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009067 if ((targetNamespace != NULL) &&
9068 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9069 /*
9070 * We are parsing the schema for schema!
9071 */
9072 pctxt->isS4S = 1;
9073 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009074 /*
9075 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009076 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009077 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9078 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9079 /*
9080 * Restore the context & schema.
9081 */
9082 schema->flags = oldFlags;
9083 schema->targetNamespace = oldTNS;
9084 if (pctxt->localImports != NULL)
9085 xmlFree((xmlChar *) pctxt->localImports);
9086 pctxt->localImports = oldLocImps;
9087 pctxt->nbLocalImports = oldNumLocImps;
9088 pctxt->sizeLocalImports = oldSizeLocImps;
9089 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009090 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009091}
9092
William M. Brack2f2a6632004-08-20 23:09:47 +00009093/**
9094 * xmlSchemaParseImport:
9095 * @ctxt: a schema validation context
9096 * @schema: the schema being built
9097 * @node: a subtree containing XML Schema informations
9098 *
9099 * parse a XML schema Import definition
9100 * *WARNING* this interface is highly subject to change
9101 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009102 * Returns 0 in case of success, a positive error code if
9103 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009104 */
9105static int
9106xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9107 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009108{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009109 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009110 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009111 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009112 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009113 xmlAttrPtr attr;
9114 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009115 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009116
9117 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9118 return (-1);
9119
9120 /*
9121 * Check for illegal attributes.
9122 */
9123 attr = node->properties;
9124 while (attr != NULL) {
9125 if (attr->ns == NULL) {
9126 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9127 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9128 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009129 xmlSchemaPIllegalAttrErr(ctxt,
9130 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9131 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009132 }
9133 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009134 xmlSchemaPIllegalAttrErr(ctxt,
9135 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9136 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009137 }
9138 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009139 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009140 /*
9141 * Extract and validate attributes.
9142 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009143 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9144 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009145 &namespaceName) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009146 xmlSchemaPSimpleTypeErr(ctxt,
9147 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
9148 NULL, node,
9149 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009150 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009151 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
9152 }
9153
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009154 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
9155 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009156 &schemaLocation) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009157 xmlSchemaPSimpleTypeErr(ctxt,
9158 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
9159 NULL, node,
9160 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009161 NULL, namespaceName, NULL, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009162 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009163 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009164 /*
9165 * And now for the children...
9166 */
9167 child = node->children;
9168 if (IS_SCHEMA(child, "annotation")) {
9169 /*
9170 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009171 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009172 */
9173 child = child->next;
9174 }
9175 if (child != NULL) {
9176 xmlSchemaPContentErr(ctxt,
9177 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
9178 NULL, NULL, node, child, NULL,
9179 "(annotation?)");
9180 }
9181 /*
9182 * Apply additional constraints.
9183 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009184 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009185 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009186 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9187 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009188 * targetNamespace [attribute].
9189 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009190 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009191 xmlSchemaPCustomErr(ctxt,
9192 XML_SCHEMAP_SRC_IMPORT_1_1,
9193 NULL, NULL, node,
9194 "The value of the attribute 'namespace' must not match "
9195 "the target namespace '%s' of the importing schema",
9196 schema->targetNamespace);
9197 return (XML_SCHEMAP_SRC_IMPORT_1_1);
9198 }
9199 } else {
9200 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009201 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009202 * <schema> must have a targetNamespace [attribute].
9203 */
9204 if (schema->targetNamespace == NULL) {
9205 xmlSchemaPCustomErr(ctxt,
9206 XML_SCHEMAP_SRC_IMPORT_1_2,
9207 NULL, NULL, node,
9208 "The attribute 'namespace' must be existent if "
9209 "the importing schema has no target namespace",
9210 NULL);
9211 return (XML_SCHEMAP_SRC_IMPORT_1_2);
9212 }
9213 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009214 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009215 * Add the namespace to the list of locally imported namespace.
9216 */
9217 if (ctxt->localImports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009218 ctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009219 sizeof(const xmlChar*));
9220 ctxt->sizeLocalImports = 10;
9221 ctxt->nbLocalImports = 0;
9222 } else if (ctxt->sizeLocalImports <= ctxt->nbLocalImports) {
9223 ctxt->sizeLocalImports *= 2;
9224 ctxt->localImports = (const xmlChar **) xmlRealloc(
9225 (xmlChar **) ctxt->localImports,
9226 ctxt->sizeLocalImports * sizeof(const xmlChar*));
9227 }
9228 ctxt->localImports[ctxt->nbLocalImports++] = namespaceName;
9229 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009230 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009231 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009232 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) ctxt,
9233 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009234 schemaLocation, &doc, &targetNamespace, 0);
9235 if (ret != 0) {
9236 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009237 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009238 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009239 } else if (doc != NULL) {
9240 xmlSchemaParseForImpInc(ctxt, schema, targetNamespace,
9241 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009242 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009243
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009244 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009245}
9246
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009247/**
9248 * xmlSchemaParseInclude:
9249 * @ctxt: a schema validation context
9250 * @schema: the schema being built
9251 * @node: a subtree containing XML Schema informations
9252 *
9253 * parse a XML schema Include definition
9254 *
William M. Bracke7091952004-05-11 15:09:58 +00009255 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009256 * 1 in case of success.
9257 */
9258static int
9259xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9260 xmlNodePtr node)
9261{
9262 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009263 const xmlChar *schemaLocation, *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009264 xmlDocPtr doc = NULL;
9265 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009266 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009267 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009268 xmlAttrPtr attr;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009269 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009270
9271
9272 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9273 return (-1);
9274
9275 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009276 * Check for illegal attributes.
9277 */
9278 attr = node->properties;
9279 while (attr != NULL) {
9280 if (attr->ns == NULL) {
9281 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9282 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009283 xmlSchemaPIllegalAttrErr(ctxt,
9284 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9285 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009286 }
9287 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009288 xmlSchemaPIllegalAttrErr(ctxt,
9289 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9290 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009291 }
9292 attr = attr->next;
9293 }
9294 /*
9295 * Extract and validate attributes.
9296 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009297 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009298 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009299 * Preliminary step, extract the URI-Reference for the include and
9300 * make an URI from the base.
9301 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009302 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9303 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009304 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009305 xmlChar *uri = NULL;
9306
9307 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9308 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009309 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009310 base = xmlNodeGetBase(node->doc, node);
9311 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009312 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009313 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00009314 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009315 xmlFree(base);
9316 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009317 if (uri == NULL) {
9318 xmlSchemaPErr(ctxt,
9319 node,
9320 XML_SCHEMAP_INTERNAL,
9321 "Internal error: xmlSchemaParseInclude, "
9322 "could not build an URI from the schemaLocation.\n",
9323 NULL, NULL);
9324 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009325 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009326 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
9327 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009328 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009329 xmlSchemaPMissingAttrErr(ctxt,
9330 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
9331 NULL, node, "schemaLocation", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009332 goto exit_invalid;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009333 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009334 /*
9335 * And now for the children...
9336 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009337 child = node->children;
9338 while (IS_SCHEMA(child, "annotation")) {
9339 /*
9340 * the annotations here are simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009341 * TODO: really?
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009342 */
9343 child = child->next;
9344 }
9345 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009346 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009347 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
9348 NULL, NULL, node, child, NULL,
9349 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009350 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009351 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009352 * Report self-inclusion.
9353 */
9354 if (xmlStrEqual(schemaLocation, ctxt->URL)) {
9355 xmlSchemaPCustomErr(ctxt,
9356 XML_SCHEMAP_SRC_INCLUDE,
9357 NULL, NULL, node,
9358 "The schema document '%s' cannot include itself.",
9359 schemaLocation);
9360 return (XML_SCHEMAP_SRC_INCLUDE);
9361 }
9362 /*
9363 * Check if this one was already processed to avoid incorrect
9364 * duplicate component errors and infinite circular inclusion.
9365 */
9366 include = schema->includes;
9367 while (include != NULL) {
9368 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
9369 targetNamespace = include->origTargetNamespace;
9370 if (targetNamespace == NULL) {
9371 /*
9372 * Chameleon include: skip only if it was build for
9373 * the targetNamespace of the including schema.
9374 */
9375 if (xmlStrEqual(schema->targetNamespace,
9376 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009377 goto check_targetNamespace;
9378 }
9379 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009380 goto check_targetNamespace;
9381 }
9382 }
9383 include = include->next;
9384 }
9385 /*
9386 * First step is to parse the input document into an DOM/Infoset
9387 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009388 */
9389 parserCtxt = xmlNewParserCtxt();
9390 if (parserCtxt == NULL) {
9391 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9392 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009393 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009394 }
9395
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009396 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
9397 xmlDictFree(parserCtxt->dict);
9398 parserCtxt->dict = ctxt->dict;
9399 xmlDictReference(parserCtxt->dict);
9400 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009401
9402 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009403 NULL, SCHEMAS_PARSE_OPTIONS);
9404 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009405 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009406 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009407 * TODO: It is not an error for the ·actual value· of the
9408 * schemaLocation [attribute] to fail to resolve it all, in which
9409 * case no corresponding inclusion is performed.
William M. Brack2f2a6632004-08-20 23:09:47 +00009410 * So do we need a warning report here?
9411 */
9412 xmlSchemaPCustomErr(ctxt,
9413 XML_SCHEMAP_FAILED_LOAD,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009414 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00009415 "Failed to load the document '%s' for inclusion", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009416 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009417 }
9418
9419 /*
9420 * Then extract the root of the schema
9421 */
9422 root = xmlDocGetRootElement(doc);
9423 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009424 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009425 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009426 NULL, NULL, node,
9427 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009428 "element", schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009429 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009430 }
9431
9432 /*
9433 * Remove all the blank text nodes
9434 */
9435 xmlSchemaCleanupDoc(ctxt, root);
9436
9437 /*
9438 * Check the schemas top level element
9439 */
9440 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009441 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009442 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009443 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009444 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009445 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009446 goto exit_invalid;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009447 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009448
William M. Brack2f2a6632004-08-20 23:09:47 +00009449 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009450 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009451 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9452 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009453 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9454 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009455check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009456 if (targetNamespace != NULL) {
9457 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009458 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009459 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009460 NULL, NULL, node,
9461 "The target namespace of the included schema "
9462 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009463 "has no target namespace",
9464 schemaLocation);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009465 goto exit_invalid;
William M. Brack2f2a6632004-08-20 23:09:47 +00009466 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
9467 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009468 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009469 NULL, NULL, node,
9470 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009471 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009472 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009473 goto exit_invalid;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009475 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009476 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009477 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009478 } else
9479 wasConvertingNs = 1;
9480 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009481
9482 if (include != NULL)
9483 goto exit;
9484
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009485 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009486 * URGENT TODO: If the schema is a chameleon-include then copy the
9487 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009488 * of those components, do nothing otherwise.
9489 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009490 * for every destinct including targetNamespace; thus not performant at
9491 * the moment.
9492 * TODO: Check when the namespace in wildcards for chameleons needs
9493 * to be converted: before we built wildcard intersections or after.
9494 */
9495 /*
9496 * Register the include.
9497 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009498 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9499 if (include == NULL) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009500 xmlSchemaPErrMemory(ctxt, "allocating include entry", NULL);
9501 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009502 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009503 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009504 include->next = schema->includes;
9505 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009506 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009507 * TODO: Use the resolved URI for the this location, since it might
9508 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009509 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009510 include->schemaLocation = schemaLocation;
9511 include->doc = doc;
9512 /*
9513 * In case of chameleons, the original target namespace will differ
9514 * from the resulting namespace.
9515 */
9516 include->origTargetNamespace = targetNamespace;
9517 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009518#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009519 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009520 xmlGenericError(xmlGenericErrorContext,
9521 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9522 " into TNS '%s'\n", schemaLocation,
9523 targetNamespace, schema->targetNamespace);
9524 else
9525 xmlGenericError(xmlGenericErrorContext,
9526 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9527 targetNamespace);
9528#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009529 /*
9530 * Compile the included schema.
9531 */
9532 xmlSchemaParseForImpInc(ctxt, schema, schema->targetNamespace, root);
9533
9534exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009535 /*
9536 * Remove the converting flag.
9537 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009538 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009539 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009540 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009541 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009542
9543exit_invalid:
9544 if (doc != NULL) {
9545 if (include != NULL)
9546 include->doc = NULL;
9547 xmlFreeDoc(doc);
9548 }
9549 return (ctxt->err);
9550
9551exit_failure:
9552 if (doc != NULL) {
9553 if (include != NULL)
9554 include->doc = NULL;
9555 xmlFreeDoc(doc);
9556 }
9557 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009558}
9559
9560/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009561 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009562 * @ctxt: a schema validation context
9563 * @schema: the schema being built
9564 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009565 * @type: the "compositor" type
9566 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009567 *
9568 * parse a XML schema Sequence definition
9569 * *WARNING* this interface is highly subject to change
9570 *
William M. Bracke7091952004-05-11 15:09:58 +00009571 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009572 * 1 in case of success.
9573 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009574static xmlSchemaTreeItemPtr
9575xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9576 xmlNodePtr node, xmlSchemaTypeType type,
9577 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009578{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009579 xmlSchemaModelGroupPtr item;
9580 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009581 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009582 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009583 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009584 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009585
9586 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009587 return (NULL);
9588 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009589 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009590 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009591 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9592 if (item == NULL)
9593 return (NULL);
9594
9595 if (withParticle) {
9596 if (type == XML_SCHEMA_TYPE_ALL) {
9597 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009598 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009599 } else {
9600 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009601 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9602 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9603 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009604 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009605 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
9606 /*
9607 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009608 */
9609 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
9610 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009611 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009612 particle->children = (xmlSchemaTreeItemPtr) item;
9613 /*
9614 * Check for illegal attributes.
9615 */
9616 attr = node->properties;
9617 while (attr != NULL) {
9618 if (attr->ns == NULL) {
9619 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9620 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
9621 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009622 xmlSchemaPIllegalAttrErr(ctxt,
9623 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9624 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009625 }
9626 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009627 xmlSchemaPIllegalAttrErr(ctxt,
9628 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9629 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009630 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009631 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00009632 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009633 } else {
9634 /*
9635 * Check for illegal attributes.
9636 */
9637 attr = node->properties;
9638 while (attr != NULL) {
9639 if (attr->ns == NULL) {
9640 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009641 xmlSchemaPIllegalAttrErr(ctxt,
9642 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9643 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009644 }
9645 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009646 xmlSchemaPIllegalAttrErr(ctxt,
9647 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9648 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009649 }
9650 attr = attr->next;
9651 }
9652
William M. Brack2f2a6632004-08-20 23:09:47 +00009653 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009654
William M. Brack2f2a6632004-08-20 23:09:47 +00009655 /*
9656 * Extract and validate attributes.
9657 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009658 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009659 /*
9660 * And now for the children...
9661 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009662 child = node->children;
9663 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009664 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009665 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009666 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009667 oldcontainer = ctxt->container;
9668 ctxt->container = container;
9669 if (type == XML_SCHEMA_TYPE_ALL) {
9670 xmlSchemaParticlePtr part, last = NULL;
9671
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009672 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009673 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
9674 schema, child, 0);
9675 if (part != NULL) {
9676 if (part->minOccurs > 1)
9677 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009678 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009679 "Invalid value for minOccurs (must be 0 or 1)", NULL);
9680 if (part->maxOccurs > 1)
9681 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009682 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009683 "Invalid value for maxOccurs (must be 0 or 1)",
9684 NULL);
9685 if (last == NULL)
9686 item->children = (xmlSchemaTreeItemPtr) part;
9687 else
9688 last->next = (xmlSchemaTreeItemPtr) part;
9689 last = part;
9690 }
9691 child = child->next;
9692 }
9693 if (child != NULL) {
9694 xmlSchemaPContentErr(ctxt,
9695 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9696 NULL, NULL, node, child, NULL,
9697 "(annotation?, (annotation?, element*)");
9698 }
9699 } else {
9700 /* choice + sequence */
9701 xmlSchemaTreeItemPtr part = NULL, last = NULL;
9702
9703 while ((IS_SCHEMA(child, "element")) ||
9704 (IS_SCHEMA(child, "group")) ||
9705 (IS_SCHEMA(child, "any")) ||
9706 (IS_SCHEMA(child, "choice")) ||
9707 (IS_SCHEMA(child, "sequence"))) {
9708
9709 if (IS_SCHEMA(child, "element")) {
9710 part = (xmlSchemaTreeItemPtr)
9711 xmlSchemaParseElement(ctxt, schema, child, 0);
9712 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009713 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009714 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9715 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009716 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009717 xmlSchemaParseAny(ctxt, schema, child);
9718 } else if (IS_SCHEMA(child, "choice")) {
9719 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9720 XML_SCHEMA_TYPE_CHOICE, 1);
9721 } else if (IS_SCHEMA(child, "sequence")) {
9722 part = xmlSchemaParseModelGroup(ctxt, schema, child,
9723 XML_SCHEMA_TYPE_SEQUENCE, 1);
9724 }
9725 if (part != NULL) {
9726 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009727 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009728 else
9729 last->next = part;
9730 last = part;
9731 }
9732 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009733 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009734 if (child != NULL) {
9735 xmlSchemaPContentErr(ctxt,
9736 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9737 NULL, NULL, node, child, NULL,
9738 "(annotation?, (element | group | choice | sequence | any)*)");
9739 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009740 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009741 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009742 if (withParticle) {
9743 if ((min == 0) && (max == 0))
9744 return (NULL);
9745 else
9746 return ((xmlSchemaTreeItemPtr) particle);
9747 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009748 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +00009749}
9750
9751/**
9752 * xmlSchemaParseRestriction:
9753 * @ctxt: a schema validation context
9754 * @schema: the schema being built
9755 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00009756 *
9757 * parse a XML schema Restriction definition
9758 * *WARNING* this interface is highly subject to change
9759 *
9760 * Returns the type definition or NULL in case of error
9761 */
9762static xmlSchemaTypePtr
9763xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009764 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +00009765{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009766 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00009767 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009768 char buf[30];
9769 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +00009770 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00009771
9772 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9773 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009774 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009775 type = ctxt->ctxtType;
9776 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009777
9778 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009779 * TODO: Is the container needed at all? the anonymous
9780 * items inside should generate unique names already.
9781 */
9782 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009783 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +00009784 /*
9785 * Check for illegal attributes.
9786 */
9787 attr = node->properties;
9788 while (attr != NULL) {
9789 if (attr->ns == NULL) {
9790 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9791 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009792 xmlSchemaPIllegalAttrErr(ctxt,
9793 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9794 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009795 }
9796 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009797 xmlSchemaPIllegalAttrErr(ctxt,
9798 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9799 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009800 }
9801 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009802 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009803 /*
9804 * Extract and validate attributes.
9805 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00009806 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00009807 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009808 * Attribute "base" - mandatory if inside a complex type.
William M. Brack2f2a6632004-08-20 23:09:47 +00009809 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009810 /*
9811 * SPEC (1.2) "otherwise (<restriction> has no <simpleType> "
9812 * among its [children]), the simple type definition which is
9813 * the {content type} of the type definition ·resolved· to by
9814 * the ·actual value· of the base [attribute]"
9815 */
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009816 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009817 NULL, NULL, node, "base",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009818 &(type->baseNs), &(type->base)) == 0) &&
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009819 (type->base == NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009820 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009821 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009822 XML_SCHEMAP_S4S_ATTR_MISSING,
9823 type, node, "base", NULL);
9824 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009825 /*
9826 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009827 */
Daniel Veillard4255d502002-04-16 15:50:10 +00009828 child = node->children;
9829 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009830 /*
9831 * Add the annotation to the simple type ancestor.
9832 */
9833 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9834 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009835 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00009836 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009837 oldcontainer = ctxt->container;
9838 ctxt->container = container;
9839 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
9840 /*
9841 * Corresponds to <simpleType><restriction><simpleType>.
9842 */
William M. Brack2f2a6632004-08-20 23:09:47 +00009843 if (IS_SCHEMA(child, "simpleType")) {
9844 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009845 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00009846 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009847 * Either the base [attribute] or the simpleType [child] of the
9848 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +00009849 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009850 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009851 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009852 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +00009853 "The attribute 'base' and the <simpleType> child are "
9854 "mutually exclusive", NULL);
9855 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009856 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +00009857 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009858 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009859 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009860 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009861 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009862 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
9863 NULL, NULL, node, child,
9864 "Either the attribute 'base' or a <simpleType> child "
9865 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00009866 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009867 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9868 /*
9869 * Corresponds to <complexType><complexContent><restriction>...
9870 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009871 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009872 * Model groups <all>, <choice> and <sequence>.
9873 */
9874 if (IS_SCHEMA(child, "all")) {
9875 type->subtypes = (xmlSchemaTypePtr)
9876 xmlSchemaParseModelGroup(ctxt, schema, child,
9877 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009878 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009879 } else if (IS_SCHEMA(child, "choice")) {
9880 type->subtypes = (xmlSchemaTypePtr)
9881 xmlSchemaParseModelGroup(ctxt,
9882 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
9883 child = child->next;
9884 } else if (IS_SCHEMA(child, "sequence")) {
9885 type->subtypes = (xmlSchemaTypePtr)
9886 xmlSchemaParseModelGroup(ctxt, schema, child,
9887 XML_SCHEMA_TYPE_SEQUENCE, 1);
9888 child = child->next;
9889 /*
9890 * Model group reference <group>.
9891 */
9892 } else if (IS_SCHEMA(child, "group")) {
9893 type->subtypes = (xmlSchemaTypePtr)
9894 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
9895 child = child->next;
9896 }
9897 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009898 /*
9899 * Corresponds to <complexType><simpleContent><restriction>...
9900 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009901 * "1.1 the simple type definition corresponding to the <simpleType>
9902 * among the [children] of <restriction> if there is one;"
9903 */
9904 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009905 /*
9906 * We will store the to-be-restricted simple type in
9907 * type->contentTypeDef *temporarily*.
9908 */
9909 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009910 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009911 if ( type->contentTypeDef == NULL)
9912 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009913 child = child->next;
9914 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009915 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009916
9917 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009918 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009919 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009920 /*
9921 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009922 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009923 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009924
Daniel Veillard01fa6152004-06-29 17:04:39 +00009925 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009926 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009927 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009928 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009929 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
9930 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009931 * *Single Facet Value*
9932 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00009933 while ((IS_SCHEMA(child, "minInclusive")) ||
9934 (IS_SCHEMA(child, "minExclusive")) ||
9935 (IS_SCHEMA(child, "maxInclusive")) ||
9936 (IS_SCHEMA(child, "maxExclusive")) ||
9937 (IS_SCHEMA(child, "totalDigits")) ||
9938 (IS_SCHEMA(child, "fractionDigits")) ||
9939 (IS_SCHEMA(child, "pattern")) ||
9940 (IS_SCHEMA(child, "enumeration")) ||
9941 (IS_SCHEMA(child, "whiteSpace")) ||
9942 (IS_SCHEMA(child, "length")) ||
9943 (IS_SCHEMA(child, "maxLength")) ||
9944 (IS_SCHEMA(child, "minLength"))) {
9945 facet = xmlSchemaParseFacet(ctxt, schema, child);
9946 if (facet != NULL) {
9947 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009948 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009949 else
9950 lastfacet->next = facet;
9951 lastfacet = facet;
9952 lastfacet->next = NULL;
9953 }
9954 child = child->next;
9955 }
9956 /*
9957 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009958 */
9959 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00009960 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
9961
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009962 facet = type->facets;
9963 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009964 facetLink = (xmlSchemaFacetLinkPtr)
9965 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +00009966 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009967 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009968 xmlFree(facetLink);
9969 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009970 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00009971 facetLink->facet = facet;
9972 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009973 if (lastFacetLink == NULL)
9974 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +00009975 else
9976 lastFacetLink->next = facetLink;
9977 lastFacetLink = facetLink;
9978 facet = facet->next;
9979 } while (facet != NULL);
9980 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009981 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009982 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
9983 /*
9984 * Attribute uses/declarations.
9985 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009986 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009987 /*
9988 * Attribute wildcard.
9989 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009990 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009991 type->attributeWildcard =
9992 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009993 child = child->next;
9994 }
9995 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009996 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009997 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
9998 xmlSchemaPContentErr(ctxt,
9999 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010000 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010001 "annotation?, (group | all | choice | sequence)?, "
10002 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010003 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010004 xmlSchemaPContentErr(ctxt,
10005 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010006 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010007 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10008 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10009 "length | minLength | maxLength | enumeration | whiteSpace | "
10010 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10011 } else {
10012 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010013 xmlSchemaPContentErr(ctxt,
10014 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010015 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010016 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10017 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10018 "length | minLength | maxLength | enumeration | whiteSpace | "
10019 "pattern)*))");
10020 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010021 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010022 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010023 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010024}
10025
10026/**
10027 * xmlSchemaParseExtension:
10028 * @ctxt: a schema validation context
10029 * @schema: the schema being built
10030 * @node: a subtree containing XML Schema informations
10031 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010032 * Parses an <extension>, which is found inside a
10033 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010034 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010035 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010036 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010037 */
10038static xmlSchemaTypePtr
10039xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010040 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010041{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010042 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010043 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010044 char buf[30];
10045 const xmlChar *oldcontainer, *container;
10046 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010047
10048 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10049 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010050 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010051 type = ctxt->ctxtType;
10052 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010053
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010054 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10055 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10056 /*
10057 * Check for illegal attributes.
10058 */
10059 attr = node->properties;
10060 while (attr != NULL) {
10061 if (attr->ns == NULL) {
10062 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10063 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010064 xmlSchemaPIllegalAttrErr(ctxt,
10065 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10066 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010067 }
10068 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010069 xmlSchemaPIllegalAttrErr(ctxt,
10070 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10071 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010072 }
10073 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010074 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010075
10076 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010077
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010078 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010079 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010080 */
10081 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010082 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10083 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010084 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010085 XML_SCHEMAP_S4S_ATTR_MISSING,
10086 NULL, node, "base", NULL);
10087 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010088 /*
10089 * And now for the children...
10090 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010091 child = node->children;
10092 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010093 /*
10094 * Add the annotation to the type ancestor.
10095 */
10096 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10097 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010098 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010099 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010100 oldcontainer = ctxt->container;
10101 ctxt->container = container;
10102 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10103 /*
10104 * Corresponds to <complexType><complexContent><extension>... and:
10105 *
10106 * Model groups <all>, <choice>, <sequence> and <group>.
10107 */
10108 if (IS_SCHEMA(child, "all")) {
10109 type->subtypes = (xmlSchemaTypePtr)
10110 xmlSchemaParseModelGroup(ctxt, schema,
10111 child, XML_SCHEMA_TYPE_ALL, 1);
10112 child = child->next;
10113 } else if (IS_SCHEMA(child, "choice")) {
10114 type->subtypes = (xmlSchemaTypePtr)
10115 xmlSchemaParseModelGroup(ctxt, schema,
10116 child, XML_SCHEMA_TYPE_CHOICE, 1);
10117 child = child->next;
10118 } else if (IS_SCHEMA(child, "sequence")) {
10119 type->subtypes = (xmlSchemaTypePtr)
10120 xmlSchemaParseModelGroup(ctxt, schema,
10121 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10122 child = child->next;
10123 } else if (IS_SCHEMA(child, "group")) {
10124 type->subtypes = (xmlSchemaTypePtr)
10125 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10126 child = child->next;
10127 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010128 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010129 if (child != NULL) {
10130 /*
10131 * Attribute uses/declarations.
10132 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010133 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010134 /*
10135 * Attribute wildcard.
10136 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010137 if (IS_SCHEMA(child, "anyAttribute")) {
10138 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010139 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10140 child = child->next;
10141 }
10142 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010143 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010144 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10145 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010146 xmlSchemaPContentErr(ctxt,
10147 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010148 NULL, NULL, node, child, NULL,
10149 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010150 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010151 } else {
10152 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010153 xmlSchemaPContentErr(ctxt,
10154 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010155 NULL, NULL, node, child, NULL,
10156 "(annotation?, ((attribute | attributeGroup)*, "
10157 "anyAttribute?))");
10158 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010159 }
10160 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010161 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010162}
10163
10164/**
10165 * xmlSchemaParseSimpleContent:
10166 * @ctxt: a schema validation context
10167 * @schema: the schema being built
10168 * @node: a subtree containing XML Schema informations
10169 *
10170 * parse a XML schema SimpleContent definition
10171 * *WARNING* this interface is highly subject to change
10172 *
10173 * Returns the type definition or NULL in case of error
10174 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010175static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010176xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
10177 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010178{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010179 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010180 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010181 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010182
10183 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010184 return (-1);
10185 /* Not a component, don't create it. */
10186 type = ctxt->ctxtType;
10187 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10188 /*
10189 * Check for illegal attributes.
10190 */
10191 attr = node->properties;
10192 while (attr != NULL) {
10193 if (attr->ns == NULL) {
10194 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010195 xmlSchemaPIllegalAttrErr(ctxt,
10196 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10197 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010198 }
10199 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010200 xmlSchemaPIllegalAttrErr(ctxt,
10201 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10202 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010203 }
10204 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010205 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010206
10207 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010208
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010209 /*
10210 * And now for the children...
10211 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010212 child = node->children;
10213 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010214 /*
10215 * Add the annotation to the complex type ancestor.
10216 */
10217 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10218 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010219 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010220 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010221 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010222 xmlSchemaParseRestriction(ctxt, schema, child,
10223 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010224 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010225 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010226 xmlSchemaParseExtension(ctxt, schema, child,
10227 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010228 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010229 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010230 if (child != NULL) {
10231 xmlSchemaPContentErr(ctxt,
10232 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010233 NULL, NULL, node, child, NULL,
10234 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010235 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010236 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010237}
10238
10239/**
10240 * xmlSchemaParseComplexContent:
10241 * @ctxt: a schema validation context
10242 * @schema: the schema being built
10243 * @node: a subtree containing XML Schema informations
10244 *
10245 * parse a XML schema ComplexContent definition
10246 * *WARNING* this interface is highly subject to change
10247 *
10248 * Returns the type definition or NULL in case of error
10249 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010250static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010251xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
10252 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +000010253{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010254 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010255 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010256 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010257
10258 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010259 return (-1);
10260 /* Not a component, don't create it. */
10261 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010262 /*
10263 * Check for illegal attributes.
10264 */
10265 attr = node->properties;
10266 while (attr != NULL) {
10267 if (attr->ns == NULL) {
10268 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010269 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010270 {
10271 xmlSchemaPIllegalAttrErr(ctxt,
10272 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10273 NULL, NULL, attr);
10274 }
10275 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10276 xmlSchemaPIllegalAttrErr(ctxt,
10277 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10278 NULL, NULL, attr);
10279 }
10280 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010281 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010282
10283 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10284
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010285 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010286 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010287 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010288 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10289 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10290 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010291 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010292 child = node->children;
10293 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010294 /*
10295 * Add the annotation to the complex type ancestor.
10296 */
10297 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10298 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010299 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010300 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010301 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010302 xmlSchemaParseRestriction(ctxt, schema, child,
10303 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010304 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010305 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010306 xmlSchemaParseExtension(ctxt, schema, child,
10307 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010308 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010309 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010310 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010311 xmlSchemaPContentErr(ctxt,
10312 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10313 NULL, NULL, node, child,
10314 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010315 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010316 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010317}
10318
10319/**
10320 * xmlSchemaParseComplexType:
10321 * @ctxt: a schema validation context
10322 * @schema: the schema being built
10323 * @node: a subtree containing XML Schema informations
10324 *
10325 * parse a XML schema Complex Type definition
10326 * *WARNING* this interface is highly subject to change
10327 *
10328 * Returns the type definition or NULL in case of error
10329 */
10330static xmlSchemaTypePtr
10331xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010332 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010333{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010334 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010335 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010336 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010337 xmlAttrPtr attr;
10338 const xmlChar *attrValue;
10339 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +000010340 char buf[40];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010341 int final = 0, block = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010342
Daniel Veillard4255d502002-04-16 15:50:10 +000010343
10344 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10345 return (NULL);
10346
Daniel Veillard01fa6152004-06-29 17:04:39 +000010347 ctxtType = ctxt->ctxtType;
10348
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010349 if (topLevel) {
10350 attr = xmlSchemaGetPropNode(node, "name");
10351 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010352 xmlSchemaPMissingAttrErr(ctxt,
10353 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010354 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010355 } else if (xmlSchemaPValAttrNode(ctxt,
10356 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010357 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10358 return (NULL);
10359 }
10360 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010361
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010362 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010363 /*
10364 * Parse as local complex type definition.
10365 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010366 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010367 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
10368 if (type == NULL)
10369 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010370 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010371 type->node = node;
10372 type->type = XML_SCHEMA_TYPE_COMPLEX;
10373 /*
10374 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010375 */
10376 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010377 /*
10378 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010379 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010380 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010381 if (type == NULL)
10382 return (NULL);
10383 type->node = node;
10384 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010385 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010386 }
10387 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010388 /*
10389 * Handle attributes.
10390 */
10391 attr = node->properties;
10392 while (attr != NULL) {
10393 if (attr->ns == NULL) {
10394 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10395 /*
10396 * Attribute "id".
10397 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010398 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10399 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010400 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10401 /*
10402 * Attribute "mixed".
10403 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010404 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010405 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010406 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10407 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010408 /*
10409 * Attributes of global complex type definitions.
10410 */
10411 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10412 /* Pass. */
10413 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10414 /*
10415 * Attribute "abstract".
10416 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010417 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
10418 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010419 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10420 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10421 /*
10422 * Attribute "final".
10423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010424 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010425 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010426 if (xmlSchemaPValAttrBlockFinal(attrValue,
10427 &(type->flags),
10428 -1,
10429 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10430 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10431 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010432 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010433 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010434 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010435 type, (xmlNodePtr) attr, NULL,
10436 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010437 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010438 } else
10439 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010440 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10441 /*
10442 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010443 */
10444 attrValue = xmlSchemaGetNodeContent(ctxt,
10445 (xmlNodePtr) attr);
10446 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010447 -1,
10448 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010449 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010450 -1, -1, -1) != 0) {
10451 xmlSchemaPSimpleTypeErr(ctxt,
10452 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010453 type, (xmlNodePtr) attr, NULL,
10454 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010455 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010456 } else
10457 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010458 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010459 xmlSchemaPIllegalAttrErr(ctxt,
10460 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010461 &des, type, attr);
10462 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010463 } else {
10464 xmlSchemaPIllegalAttrErr(ctxt,
10465 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010466 &des, type, attr);
10467 }
10468 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010469 xmlSchemaPIllegalAttrErr(ctxt,
10470 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10471 &des, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010472 }
10473 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010474 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010475 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010476 /*
10477 * Apply default "block" values.
10478 */
10479 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10480 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10481 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10482 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10483 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010484 if (! final) {
10485 /*
10486 * Apply default "block" values.
10487 */
10488 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10489 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10490 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10491 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10492 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010493 /*
10494 * And now for the children...
10495 */
10496 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010497 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010498 child = node->children;
10499 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010500 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10501 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010502 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010503 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010504 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010505 /*
10506 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010507 * Specifying mixed='true' when the <simpleContent>
10508 * alternative is chosen has no effect
10509 */
William M. Bracke7091952004-05-11 15:09:58 +000010510 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10511 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010512 xmlSchemaParseSimpleContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010513 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010514 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010515 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
10516 xmlSchemaParseComplexContent(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010517 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010518 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010519 /*
10520 * SPEC
10521 * "...the third alternative (neither <simpleContent> nor
10522 * <complexContent>) is chosen. This case is understood as shorthand
10523 * for complex content restricting the ·ur-type definition·, and the
10524 * details of the mappings should be modified as necessary.
10525 */
10526 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
10527 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010528 /*
10529 * Parse model groups.
10530 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010531 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010532 type->subtypes = (xmlSchemaTypePtr)
10533 xmlSchemaParseModelGroup(ctxt, schema, child,
10534 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010535 child = child->next;
10536 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010537 type->subtypes = (xmlSchemaTypePtr)
10538 xmlSchemaParseModelGroup(ctxt, schema, child,
10539 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010540 child = child->next;
10541 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010542 type->subtypes = (xmlSchemaTypePtr)
10543 xmlSchemaParseModelGroup(ctxt, schema, child,
10544 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010545 child = child->next;
10546 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010547 type->subtypes = (xmlSchemaTypePtr)
10548 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010549 child = child->next;
10550 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010551 /*
10552 * Parse attribute decls/refs.
10553 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010554 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010555 /*
10556 * Parse attribute wildcard.
10557 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010558 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010559 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
10560 child = child->next;
10561 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010562 }
10563 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010564 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010565 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010566 &des, type, node, child,
10567 NULL, "(annotation?, (simpleContent | complexContent | "
10568 "((group | all | choice | sequence)?, ((attribute | "
10569 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010570 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010571 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +000010572 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010573 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010574 return (type);
10575}
10576
Daniel Veillard4255d502002-04-16 15:50:10 +000010577/**
10578 * xmlSchemaParseSchema:
10579 * @ctxt: a schema validation context
10580 * @node: a subtree containing XML Schema informations
10581 *
10582 * parse a XML schema definition from a node set
10583 * *WARNING* this interface is highly subject to change
10584 *
10585 * Returns the internal XML Schema structure built from the resource or
10586 * NULL in case of error
10587 */
10588static xmlSchemaPtr
10589xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
10590{
10591 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010592 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010593 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010594 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010595
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010596 /*
10597 * This one is called by xmlSchemaParse only and is used if
10598 * the schema to be parsed was specified via the API; i.e. not
10599 * automatically by the validated instance document.
10600 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010601 if ((ctxt == NULL) || (node == NULL))
10602 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010603 nberrors = ctxt->nberrors;
10604 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010605 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010606 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010607 xmlSchemaImportPtr import;
10608
Daniel Veillard4255d502002-04-16 15:50:10 +000010609 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010610 if (schema == NULL)
10611 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010612 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000010613 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010614 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010615 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
10616 /*
10617 * TODO: Should we proceed with an invalid target namespace?
10618 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010619 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000010620 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
10621 /*
10622 * We are parsing the schema for schema!
10623 */
10624 ctxt->isS4S = 1;
10625 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010626 } else {
10627 schema->targetNamespace = NULL;
10628 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010629 /*
10630 * Add the current ns name and location to the import table;
10631 * this is needed to have a consistent mechanism, regardless
10632 * if all schemata are constructed dynamically fired by the
10633 * instance or if the schema to be used was specified via
10634 * the API.
10635 */
10636 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
10637 schema->targetNamespace);
10638 if (import == NULL) {
10639 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
10640 NULL, NULL, (xmlNodePtr) ctxt->doc,
10641 "Internal error: xmlSchemaParseSchema, "
10642 "failed to add an import entry", NULL);
10643 xmlSchemaFree(schema);
10644 schema = NULL;
10645 return (NULL);
10646 }
10647 import->schemaLocation = ctxt->URL;
10648 /*
10649 * NOTE: We won't set the doc here, otherwise it will be freed
10650 * if the import struct is freed.
10651 * import->doc = ctxt->doc;
10652 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010653 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010654 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
10655 } else {
10656 xmlDocPtr doc;
10657
10658 doc = node->doc;
10659
10660 if ((doc != NULL) && (doc->URL != NULL)) {
10661 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10662 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010663 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010664 } else {
10665 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
10666 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010667 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000010668 }
10669 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010670 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010671 if (ctxt->nberrors != 0) {
10672 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010673 xmlSchemaFree(schema);
10674 schema = NULL;
10675 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010676 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010677 if (schema != NULL)
10678 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000010679 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000010680#ifdef DEBUG
10681 if (schema == NULL)
10682 xmlGenericError(xmlGenericErrorContext,
10683 "xmlSchemaParse() failed\n");
10684#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000010685 return (schema);
10686}
10687
10688/************************************************************************
10689 * *
10690 * Validating using Schemas *
10691 * *
10692 ************************************************************************/
10693
10694/************************************************************************
10695 * *
10696 * Reading/Writing Schemas *
10697 * *
10698 ************************************************************************/
10699
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010700#if 0 /* Will be enabled if it is clear what options are needed. */
10701/**
10702 * xmlSchemaParserCtxtSetOptions:
10703 * @ctxt: a schema parser context
10704 * @options: a combination of xmlSchemaParserOption
10705 *
10706 * Sets the options to be used during the parse.
10707 *
10708 * Returns 0 in case of success, -1 in case of an
10709 * API error.
10710 */
10711static int
10712xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
10713 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010714
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010715{
10716 int i;
10717
10718 if (ctxt == NULL)
10719 return (-1);
10720 /*
10721 * WARNING: Change the start value if adding to the
10722 * xmlSchemaParseOption.
10723 */
10724 for (i = 1; i < (int) sizeof(int) * 8; i++) {
10725 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010726 return (-1);
10727 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010728 }
10729 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010730 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010731}
10732
10733/**
10734 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010735 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010736 *
10737 * Returns the option combination of the parser context.
10738 */
10739static int
10740xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010741
10742{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010743 if (ctxt == NULL)
10744 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010745 else
10746 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010747}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010748#endif
10749
Daniel Veillard4255d502002-04-16 15:50:10 +000010750/**
10751 * xmlSchemaNewParserCtxt:
10752 * @URL: the location of the schema
10753 *
10754 * Create an XML Schemas parse context for that file/resource expected
10755 * to contain an XML Schemas file.
10756 *
10757 * Returns the parser context or NULL in case of error
10758 */
10759xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010760xmlSchemaNewParserCtxt(const char *URL)
10761{
Daniel Veillard4255d502002-04-16 15:50:10 +000010762 xmlSchemaParserCtxtPtr ret;
10763
10764 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010765 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010766
10767 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10768 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010769 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010770 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010771 return (NULL);
10772 }
10773 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010774 ret->type = XML_SCHEMA_CTXT_PARSER;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010775 ret->dict = xmlDictCreate();
10776 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000010777 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000010778 return (ret);
10779}
10780
10781/**
Daniel Veillard6045c902002-10-09 21:13:59 +000010782 * xmlSchemaNewMemParserCtxt:
10783 * @buffer: a pointer to a char array containing the schemas
10784 * @size: the size of the array
10785 *
10786 * Create an XML Schemas parse context for that memory buffer expected
10787 * to contain an XML Schemas file.
10788 *
10789 * Returns the parser context or NULL in case of error
10790 */
10791xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010792xmlSchemaNewMemParserCtxt(const char *buffer, int size)
10793{
Daniel Veillard6045c902002-10-09 21:13:59 +000010794 xmlSchemaParserCtxtPtr ret;
10795
10796 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010797 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010798
10799 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10800 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010801 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010802 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000010803 return (NULL);
10804 }
10805 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10806 ret->buffer = buffer;
10807 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010808 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000010809 return (ret);
10810}
10811
10812/**
Daniel Veillard9d751502003-10-29 13:21:47 +000010813 * xmlSchemaNewDocParserCtxt:
10814 * @doc: a preparsed document tree
10815 *
10816 * Create an XML Schemas parse context for that document.
10817 * NB. The document may be modified during the parsing process.
10818 *
10819 * Returns the parser context or NULL in case of error
10820 */
10821xmlSchemaParserCtxtPtr
10822xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
10823{
10824 xmlSchemaParserCtxtPtr ret;
10825
10826 if (doc == NULL)
10827 return (NULL);
10828
10829 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10830 if (ret == NULL) {
10831 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10832 NULL);
10833 return (NULL);
10834 }
10835 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10836 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000010837 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000010838 /* The application has responsibility for the document */
10839 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000010840
10841 return (ret);
10842}
10843
10844/**
Daniel Veillard4255d502002-04-16 15:50:10 +000010845 * xmlSchemaFreeParserCtxt:
10846 * @ctxt: the schema parser context
10847 *
10848 * Free the resources associated to the schema parser context
10849 */
10850void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010851xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
10852{
Daniel Veillard4255d502002-04-16 15:50:10 +000010853 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010854 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000010855 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010856 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010857 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010858 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010859 xmlFree(ctxt->assemble);
10860 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010861 if (ctxt->vctxt != NULL) {
10862 xmlSchemaFreeValidCtxt(ctxt->vctxt);
10863 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000010864 if (ctxt->localImports != NULL)
10865 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010866 if (ctxt->substGroups != NULL)
10867 xmlHashFree(ctxt->substGroups,
10868 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000010869 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000010870 xmlFree(ctxt);
10871}
10872
10873/************************************************************************
10874 * *
10875 * Building the content models *
10876 * *
10877 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010878
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010879static void
10880xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000010881 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010882{
Daniel Veillarda980bef2005-07-18 21:34:03 +000010883 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010884 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010885 xmlSchemaSubstGroupPtr substGroup;
10886 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010887
10888 elemDecl = (xmlSchemaElementPtr) particle->children;
10889 /*
10890 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010891 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010892 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000010893 if (end == NULL)
10894 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010895 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
10896 if (substGroup == NULL) {
10897 xmlSchemaPErr(pctxt, GET_NODE(particle),
10898 XML_SCHEMAP_INTERNAL,
10899 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
10900 "declaration is marked having a subst. group but none "
10901 "available.\n", elemDecl->name, NULL);
10902 return;
10903 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000010904 if (counter >= 0) {
10905 /*
10906 * NOTE that we put the declaration in, even if it's abstract,
10907 */
10908 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
10909 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10910 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10911 /*
10912 * Add subst. group members.
10913 */
10914 for (i = 0; i < substGroup->members->nbItems; i++) {
10915 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10916 xmlAutomataNewTransition2(pctxt->am, tmp, end,
10917 member->name, member->targetNamespace, member);
10918 }
10919 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010920 /*
10921 * NOTE that we put the declaration in, even if it's abstract,
10922 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010923 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010924 xmlAutomataNewTransition2(pctxt->am,
10925 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010926 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
10927 /*
10928 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010929 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010930 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010931 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000010932 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
10933 member->name, member->targetNamespace,
10934 1, 1, member);
10935 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010936 }
10937 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010938 xmlAutomataStatePtr hop;
10939 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
10940 UNBOUNDED : particle->maxOccurs - 1;
10941 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
10942
10943 counter =
10944 xmlAutomataNewCounter(pctxt->am, minOccurs,
10945 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010946 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010947
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010948 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010949 xmlAutomataNewTransition2(pctxt->am,
10950 start, NULL,
10951 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010952 hop);
10953 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000010954 * Add subst. group members.
10955 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010956 for (i = 0; i < substGroup->members->nbItems; i++) {
10957 member = (xmlSchemaElementPtr) substGroup->members->items[i];
10958 xmlAutomataNewEpsilon(pctxt->am,
10959 xmlAutomataNewTransition2(pctxt->am,
10960 start, NULL,
10961 member->name, member->targetNamespace, member),
10962 hop);
10963 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010964 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
10965 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
10966 }
10967 if (particle->minOccurs == 0)
10968 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010969 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010970}
10971
10972static void
10973xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
10974 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010975{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000010976 if (((xmlSchemaElementPtr) particle->children)->flags &
10977 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010978 /*
10979 * Substitution groups.
10980 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000010981 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010982 } else {
10983 xmlSchemaElementPtr elemDecl;
10984 xmlAutomataStatePtr start;
10985
10986 elemDecl = (xmlSchemaElementPtr) particle->children;
10987
10988 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010989 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010990 if (particle->maxOccurs == 1) {
10991 start = ctxt->state;
10992 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000010993 elemDecl->name, elemDecl->targetNamespace, elemDecl);
10994 } else if ((particle->maxOccurs >= UNBOUNDED) &&
10995 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010996 /* Special case. */
10997 start = ctxt->state;
10998 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
10999 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011000 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011001 } else {
11002 int counter;
11003 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11004 UNBOUNDED : particle->maxOccurs - 1;
11005 int minOccurs = particle->minOccurs < 1 ?
11006 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011007
11008 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011009 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11010 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11011 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11012 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11013 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11014 NULL, counter);
11015 }
11016 if (particle->minOccurs == 0)
11017 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11018 }
11019}
11020
Daniel Veillard4255d502002-04-16 15:50:10 +000011021/**
11022 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011023 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011024 * @particle: the particle component
11025 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011026 *
11027 * Generate the automata sequence needed for that type
11028 */
11029static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011030xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011031 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011032 const xmlChar * name)
11033{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011034 if (particle == NULL) {
11035 xmlSchemaPErr(ctxt, NULL,
11036 XML_SCHEMAP_INTERNAL,
11037 "Internal error: xmlSchemaBuildAContentModel, "
11038 "particle is NULL.\n", NULL, NULL);
11039 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011040 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011041 if (particle->children == NULL) {
11042 xmlSchemaPErr(ctxt, GET_NODE(particle),
11043 XML_SCHEMAP_INTERNAL,
11044 "Internal error: xmlSchemaBuildAContentModel, "
11045 "no term on particle.\n", NULL, NULL);
11046 return;
11047 }
11048
11049 switch (particle->children->type) {
11050 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011051 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011052 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011053 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011054
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011055 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011056
Daniel Veillardc0826a72004-08-10 14:17:33 +000011057 start = ctxt->state;
11058 end = xmlAutomataNewState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011059
11060 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011061 if (wild->any == 1) {
11062 /*
11063 * We need to add both transitions:
11064 *
11065 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011066 */
11067 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011068 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011069 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011070 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11071 /*
11072 * 2. the {"*"} for elements in no namespace.
11073 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011074 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011075 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011076 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011077 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11078
11079 } else if (wild->nsSet != NULL) {
11080 ns = wild->nsSet;
11081 do {
11082 ctxt->state = start;
11083 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011084 ctxt->state, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011085 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11086 ns = ns->next;
11087 } while (ns != NULL);
11088
11089 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011090
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011091 /*
11092 * Lead nodes with the negated namespace to the sink-state
11093 * {"*", "##other"}.
11094 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011095 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011096 BAD_CAST "*", wild->negNsSet->value, wild);
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011097 /*
11098 * Open a door for nodes with any other namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011099 * {"*", "*"}
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +000011100 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011101 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011102 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011103 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011104 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011105 } else {
11106 int counter;
11107 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011108 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011109 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011110 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011111 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011112
Daniel Veillardc0826a72004-08-10 14:17:33 +000011113 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011114 hop = xmlAutomataNewState(ctxt->am);
11115 if (wild->any == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011116 ctxt->state =
11117 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011118 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011119 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011120 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011121 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011122 start, NULL, BAD_CAST "*", NULL, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011123 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011124 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011125 ns = wild->nsSet;
11126 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011127 ctxt->state =
Daniel Veillardc0826a72004-08-10 14:17:33 +000011128 xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011129 start, NULL, BAD_CAST "*", ns->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011130 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
11131 ns = ns->next;
11132 } while (ns != NULL);
11133
11134 } else if (wild->negNsSet != NULL) {
11135 xmlAutomataStatePtr deadEnd;
11136
11137 deadEnd = xmlAutomataNewState(ctxt->am);
11138 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011139 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011140 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011141 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011142 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011143 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011144 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
11145 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
11146 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011147 if (particle->minOccurs == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011148 xmlAutomataNewEpsilon(ctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011149 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011150 ctxt->state = end;
11151 break;
11152 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011153 case XML_SCHEMA_TYPE_ELEMENT:
11154 xmlSchemaBuildContentModelForElement(ctxt, particle);
11155 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011156 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011157 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011158
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011159 /*
11160 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011161 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011162 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011163 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11164 sub = particle->children->children;
11165 while (sub != NULL) {
11166 xmlSchemaBuildAContentModel(ctxt,
11167 (xmlSchemaParticlePtr) sub, name);
11168 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011169 }
11170 } else {
11171 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011172
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011173 if (particle->maxOccurs >= UNBOUNDED) {
11174 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011175 xmlAutomataStatePtr tmp;
11176 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011177
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011178 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011179 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011180 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011181
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011182 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011183 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011184
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011185 sub = particle->children->children;
11186 while (sub != NULL) {
11187 xmlSchemaBuildAContentModel(ctxt,
11188 (xmlSchemaParticlePtr) sub, name);
11189 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011190 }
11191 tmp = ctxt->state;
11192 xmlAutomataNewCountedTrans(ctxt->am, tmp,
11193 oldstate, counter);
11194 ctxt->state =
11195 xmlAutomataNewCounterTrans(ctxt->am, tmp,
11196 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011197
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011198 } else {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011199 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11200 oldstate, NULL);
11201 oldstate = ctxt->state;
11202
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011203 sub = particle->children->children;
11204 while (sub != NULL) {
11205 xmlSchemaBuildAContentModel(ctxt,
11206 (xmlSchemaParticlePtr) sub, name);
11207 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011208 }
11209 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
11210 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011211 /*
11212 * epsilon needed to block previous trans from
11213 * being allowed to enter back from another
11214 * construct
11215 */
11216 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
11217 ctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011218 if (particle->minOccurs == 0) {
11219 xmlAutomataNewEpsilon(ctxt->am,
11220 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011221 }
11222 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011223 } else if ((particle->maxOccurs > 1)
11224 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011225 xmlAutomataStatePtr tmp;
11226 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011227
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011228 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011229 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011230 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011231
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011232 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011233 particle->minOccurs - 1,
11234 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011235
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011236 sub = particle->children->children;
11237 while (sub != NULL) {
11238 xmlSchemaBuildAContentModel(ctxt,
11239 (xmlSchemaParticlePtr) sub, name);
11240 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011241 }
11242 tmp = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011243 xmlAutomataNewCountedTrans(ctxt->am,
11244 tmp, oldstate, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011245 ctxt->state =
11246 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
11247 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011248 if (particle->minOccurs == 0) {
11249 xmlAutomataNewEpsilon(ctxt->am,
11250 oldstate, ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011251 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011252 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011253 sub = particle->children->children;
11254 while (sub != NULL) {
11255 xmlSchemaBuildAContentModel(ctxt,
11256 (xmlSchemaParticlePtr) sub, name);
11257 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011258 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011259 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011260 xmlAutomataNewEpsilon(ctxt->am, oldstate,
11261 ctxt->state);
11262 }
11263 }
11264 }
11265 break;
11266 }
11267 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011268 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011269 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011270
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011271 start = ctxt->state;
11272 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011273
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011274 /*
11275 * iterate over the subtypes and remerge the end with an
11276 * epsilon transition
11277 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011278 if (particle->maxOccurs == 1) {
11279 sub = particle->children->children;
11280 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011281 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011282 xmlSchemaBuildAContentModel(ctxt,
11283 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011284 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011285 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011286 }
11287 } else {
11288 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011289 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011290 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11291 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011292 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011293 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011294
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011295 /*
11296 * use a counter to keep track of the number of transtions
11297 * which went through the choice.
11298 */
11299 counter =
Daniel Veillardafc05b62005-07-17 06:11:19 +000011300 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011301 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011302 base = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011303
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011304 sub = particle->children->children;
11305 while (sub != NULL) {
Daniel Veillardafc05b62005-07-17 06:11:19 +000011306 ctxt->state = base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011307 xmlSchemaBuildAContentModel(ctxt,
11308 (xmlSchemaParticlePtr) sub, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011309 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011310 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011311 }
Daniel Veillardafc05b62005-07-17 06:11:19 +000011312 xmlAutomataNewEpsilon(ctxt->am, start, base);
11313 xmlAutomataNewCountedTrans(ctxt->am, hop, base, counter);
11314 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011315 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011316 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011317 xmlAutomataNewEpsilon(ctxt->am, start, end);
11318 }
11319 ctxt->state = end;
11320 break;
11321 }
11322 case XML_SCHEMA_TYPE_ALL:{
Daniel Veillarda980bef2005-07-18 21:34:03 +000011323 xmlAutomataStatePtr start, hop;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011324 xmlSchemaParticlePtr sub;
11325 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011326 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011327
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011328 sub = (xmlSchemaParticlePtr) particle->children->children;
11329 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011330 break;
11331 start = ctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011332 while (sub != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011333 ctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011334
11335 elemDecl = (xmlSchemaElementPtr) sub->children;
11336 if (elemDecl == NULL) {
11337 xmlSchemaPErr(ctxt, NULL,
11338 XML_SCHEMAP_INTERNAL,
11339 "Internal error: xmlSchemaBuildAContentModel, "
11340 "<element> particle a NULL term.\n", NULL, NULL);
11341 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011342 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011343 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011344 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011345 * {particles} of the group must be 0 or 1; this is
11346 * already ensured during the parse of the content of
11347 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011348 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011349 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11350 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011351
Daniel Veillarda980bef2005-07-18 21:34:03 +000011352 /*
11353 * This is an abstract group, we need to share
11354 * the same counter for all the element transitions
11355 * derived from the group
11356 */
11357 counter = xmlAutomataNewCounter(ctxt->am,
11358 sub->minOccurs, sub->maxOccurs);
11359 xmlSchemaBuildContentModelForSubstGroup(ctxt,
11360 sub, counter, ctxt->state);
11361 } else {
11362 if ((sub->minOccurs == 1) &&
11363 (sub->maxOccurs == 1)) {
11364 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
11365 ctxt->state,
11366 elemDecl->name,
11367 elemDecl->targetNamespace,
11368 1, 1, elemDecl);
11369 } else if ((sub->minOccurs == 0) &&
11370 (sub->maxOccurs == 1)) {
11371
11372 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
11373 ctxt->state,
11374 elemDecl->name,
11375 elemDecl->targetNamespace,
11376 0,
11377 1,
11378 elemDecl);
11379 }
11380 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011381 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011382 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011383 lax = particle->minOccurs == 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011384 ctxt->state =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011385 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011386 break;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011387#if 0
11388 xmlAutomataStatePtr start, end, base;
11389 xmlSchemaParticlePtr sub;
11390 xmlSchemaElementPtr elemDecl;
11391 int nbtrans = 0;
11392 int lax = particle->minOccurs == 0;
11393 int counter = -1;
11394
11395 sub = (xmlSchemaParticlePtr) particle->children->children;
11396 if (sub == NULL)
11397 break;
11398
11399 start = ctxt->state;
11400 end = xmlAutomataNewState(ctxt->am);
11401 base = xmlAutomataNewState(ctxt->am);
11402 xmlAutomataNewEpsilon(ctxt->am, start, base);
11403
11404 if (!lax) {
11405 while (sub != NULL) {
11406 sub = (xmlSchemaParticlePtr) sub->next;
11407 nbtrans++;
11408 }
11409 sub = (xmlSchemaParticlePtr) particle->children->children;
11410 nbtrans--;
11411 counter = xmlAutomataNewCounter(ctxt->am, nbtrans, nbtrans);
11412 }
11413
11414 while (sub != NULL) {
11415 ctxt->state = base;
11416
11417 elemDecl = (xmlSchemaElementPtr) sub->children;
11418 if (elemDecl == NULL) {
11419 xmlSchemaPErr(ctxt, NULL,
11420 XML_SCHEMAP_INTERNAL,
11421 "Internal error: xmlSchemaBuildAContentModel, "
11422 "<element> particle a NULL term.\n", NULL, NULL);
11423 return;
11424 };
11425 xmlSchemaBuildContentModelForElement(ctxt,
11426 (xmlSchemaParticlePtr) sub, 1);
11427 if (lax) {
11428 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, base);
11429 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
11430 } else {
11431 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state,
11432 base, counter);
11433 xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11434 end, counter);
11435 }
11436 sub = (xmlSchemaParticlePtr) sub->next;
11437 }
11438 ctxt->state = end;
11439 break;
11440#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011441 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011442 default:
11443 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011444 "Internal error: xmlSchemaBuildAContentModel, found "
11445 "unexpected term of type %d in content model of complex "
11446 "type '%s'.\n",
11447 particle->children->type, name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011448 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011449 }
11450}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011451
Daniel Veillard4255d502002-04-16 15:50:10 +000011452/**
11453 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011454 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011455 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011456 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011457 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011458 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011459 */
11460static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011461xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011462 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011463 const xmlChar * name)
11464{
Daniel Veillard4255d502002-04-16 15:50:10 +000011465 xmlAutomataStatePtr start;
11466
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011467 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11468 (type->contModel != NULL) ||
11469 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11470 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011471 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011472
11473#ifdef DEBUG_CONTENT
11474 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011475 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011476#endif
11477
Daniel Veillard4255d502002-04-16 15:50:10 +000011478 ctxt->am = xmlNewAutomata();
11479 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011480 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011481 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011482 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011483 }
11484 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011485 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011486 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011487 type->contModel = xmlAutomataCompile(ctxt->am);
11488 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011489 xmlSchemaPCustomErr(ctxt,
11490 XML_SCHEMAP_INTERNAL,
11491 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011492 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011493 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011494 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011495 XML_SCHEMAP_NOT_DETERMINISTIC,
11496 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011497 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011498 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011499 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011500#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011501 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011502 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011503 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011504#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011505 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011506 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011507 xmlFreeAutomata(ctxt->am);
11508 ctxt->am = NULL;
11509}
11510
11511/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011512 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011513 * @elem: the schema element context
11514 * @ctxt: the schema parser context
11515 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011516 * Resolves the references of an element declaration
11517 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011518 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011519 */
11520static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011521xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011522 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011523 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011524 const xmlChar * context ATTRIBUTE_UNUSED,
11525 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011526{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011527 if ((ctxt == NULL) || (elemDecl == NULL) ||
11528 ((elemDecl != NULL) &&
11529 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011530 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011531 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011532
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011533 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011534 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011535
11536 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011537 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011538 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011539 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011540 elemDecl->namedTypeNs);
11541 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011542 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011543 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011544 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011545 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011546 XML_SCHEMA_TYPE_BASIC, "type definition");
11547 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011548 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011549 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011550 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011551 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011552
Daniel Veillardc0826a72004-08-10 14:17:33 +000011553 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011554 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011555 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011556 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011557 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11558 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011559 if (substHead == NULL) {
11560 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011561 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011562 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011563 "substitutionGroup", elemDecl->substGroup,
11564 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011565 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011566 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011567 /*
11568 * Set the "substitution group affiliation".
11569 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011570 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011571 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011572 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011573 * (type definition)...otherwise the {type definition} of the
11574 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011575 * the substitutionGroup [attribute], if present
11576 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011577 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011578 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011579 }
11580 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011581 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11582 (elemDecl->substGroup == NULL))
11583 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000011584}
11585
11586/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011587 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000011588 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011589 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000011590 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011591 * Checks and builds the "member type definitions" property of the union
11592 * simple type. This handles part (1), part (2) is done in
11593 * xmlSchemaFinishMemberTypeDefinitionsProperty()
11594 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000011595 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000011596 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011597static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011598xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
11599 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000011600{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011601
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011602 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011603 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000011604
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011605 /*
11606 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
11607 * define the explicit members as the type definitions ·resolved·
11608 * to by the items in the ·actual value· of the memberTypes [attribute],
11609 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011610 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000011611 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011612 /*
11613 * Resolve references.
11614 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011615 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011616 lastLink = NULL;
11617 while (link != NULL) {
11618 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011619
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011620 name = ((xmlSchemaQNameRefPtr) link->type)->name;
11621 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
11622
11623 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
11624 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
11625 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011626 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011627 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
11628 /*
11629 * Remove the member type link.
11630 */
11631 if (lastLink == NULL)
11632 type->memberTypes = link->next;
11633 else
11634 lastLink->next = link->next;
11635 newLink = link;
11636 link = link->next;
11637 xmlFree(newLink);
11638 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011639 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011640 lastLink = link;
11641 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011642 }
11643 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011644 /*
11645 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011646 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011647 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011648 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000011649 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
11650 if (link == NULL) {
11651 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
11652 return (-1);
11653 }
11654 link->type = memberType;
11655 link->next = NULL;
11656 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011657 type->memberTypes = link;
11658 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000011659 lastLink->next = link;
11660 lastLink = link;
11661 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011662 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011663 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000011664}
11665
Daniel Veillard4255d502002-04-16 15:50:10 +000011666/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011667 * xmlSchemaIsDerivedFromBuiltInType:
11668 * @ctxt: the schema parser context
11669 * @type: the type definition
11670 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011671 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011672 *
11673 * Returns 1 if the type has the given value type, or
11674 * is derived from such a type.
11675 */
William M. Brack803812b2004-06-03 02:11:24 +000011676static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011677xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000011678{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011679 if (type == NULL)
11680 return (0);
11681 if (IS_COMPLEX_TYPE(type))
11682 return (0);
11683 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11684 if (type->builtInType == valType)
11685 return(1);
11686 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11687 (type->builtInType == XML_SCHEMAS_ANYTYPE))
11688 return (0);
11689 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11690 } else
11691 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000011692
11693 return (0);
11694}
11695
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011696#if 0
11697/**
11698 * xmlSchemaIsDerivedFromBuiltInType:
11699 * @ctxt: the schema parser context
11700 * @type: the type definition
11701 * @valType: the value type
11702 *
11703 *
11704 * Returns 1 if the type has the given value type, or
11705 * is derived from such a type.
11706 */
11707static int
11708xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
11709{
11710 if (type == NULL)
11711 return (0);
11712 if (IS_COMPLEX_TYPE(type))
11713 return (0);
11714 if (type->type == XML_SCHEMA_TYPE_BASIC) {
11715 if (type->builtInType == valType)
11716 return(1);
11717 return (0);
11718 } else
11719 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
11720
11721 return (0);
11722}
11723#endif
11724
11725static xmlSchemaTypePtr
11726xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
11727{
11728 if (type == NULL)
11729 return (NULL);
11730 if (IS_COMPLEX_TYPE(type))
11731 return (NULL);
11732 if (type->type == XML_SCHEMA_TYPE_BASIC)
11733 return(type);
11734 else
11735 return(xmlSchemaQueryBuiltInType(type->subtypes));
11736
11737 return (NULL);
11738}
11739
Daniel Veillard3646d642004-06-02 19:19:14 +000011740/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011741 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000011742 * @type: the simpleType definition
11743 *
11744 * Returns the primitive type of the given type or
11745 * NULL in case of error.
11746 */
11747static xmlSchemaTypePtr
11748xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
11749{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011750
Daniel Veillard01fa6152004-06-29 17:04:39 +000011751 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011752 /*
11753 * Note that anySimpleType is actually not a primitive type
11754 * but we need that here.
11755 */
11756 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
11757 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000011758 return (type);
11759 type = type->baseType;
11760 }
11761
11762 return (NULL);
11763}
11764
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011765#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011766/**
11767 * xmlSchemaGetBuiltInTypeAncestor:
11768 * @type: the simpleType definition
11769 *
11770 * Returns the primitive type of the given type or
11771 * NULL in case of error.
11772 */
11773static xmlSchemaTypePtr
11774xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
11775{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011776 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000011777 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011778 while (type != NULL) {
11779 if (type->type == XML_SCHEMA_TYPE_BASIC)
11780 return (type);
11781 type = type->baseType;
11782 }
11783
11784 return (NULL);
11785}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000011786#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000011787
Daniel Veillard01fa6152004-06-29 17:04:39 +000011788/**
Daniel Veillard3646d642004-06-02 19:19:14 +000011789 * xmlSchemaBuildAttributeUsesOwned:
11790 * @ctxt: the schema parser context
11791 * @type: the complex type definition
11792 * @cur: the attribute declaration list
11793 * @lastUse: the top of the attribute use list
11794 *
11795 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011796 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000011797 * xmlSchemaBuildAttributeValidation only.
11798 */
11799static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011800xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011801 xmlSchemaAttributePtr cur,
11802 xmlSchemaAttributeLinkPtr *uses,
11803 xmlSchemaAttributeLinkPtr *lastUse)
11804{
11805 xmlSchemaAttributeLinkPtr tmp;
11806 while (cur != NULL) {
11807 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011808 /*
11809 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
11810 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000011811 * <attributeGroup> [children], if any."
11812 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011813 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
11814 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000011815 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011816 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011817 }
11818 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011819 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000011820 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011821 */
11822 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000011823 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11824 if (tmp == NULL) {
11825 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
11826 return (-1);
11827 }
11828 tmp->attr = cur;
11829 tmp->next = NULL;
11830 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011831 *uses = tmp;
11832 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011833 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011834 *lastUse = tmp;
11835 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011836 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011837 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011838 return (0);
11839}
11840
Daniel Veillard50355f02004-06-08 17:52:16 +000011841/**
11842 * xmlSchemaCloneWildcardNsConstraints:
11843 * @ctxt: the schema parser context
11844 * @dest: the destination wildcard
11845 * @source: the source wildcard
11846 *
11847 * Clones the namespace constraints of source
11848 * and assignes them to dest.
11849 * Returns -1 on internal error, 0 otherwise.
11850 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011851static int
11852xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
11853 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011854 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000011855{
11856 xmlSchemaWildcardNsPtr cur, tmp, last;
11857
11858 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011859 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011860 (*dest)->any = source->any;
11861 cur = source->nsSet;
11862 last = NULL;
11863 while (cur != NULL) {
11864 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
11865 if (tmp == NULL)
11866 return(-1);
11867 tmp->value = cur->value;
11868 if (last == NULL)
11869 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011870 else
Daniel Veillard3646d642004-06-02 19:19:14 +000011871 last->next = tmp;
11872 last = tmp;
11873 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011874 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011875 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011876 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000011877 if (source->negNsSet != NULL) {
11878 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
11879 if ((*dest)->negNsSet == NULL)
11880 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011881 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000011882 } else
11883 (*dest)->negNsSet = NULL;
11884 return(0);
11885}
11886
Daniel Veillard50355f02004-06-08 17:52:16 +000011887/**
11888 * xmlSchemaUnionWildcards:
11889 * @ctxt: the schema parser context
11890 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011891 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000011892 *
11893 * Unions the namespace constraints of the given wildcards.
11894 * @completeWild will hold the resulting union.
11895 * Returns a positive error code on failure, -1 in case of an
11896 * internal error, 0 otherwise.
11897 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011898static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011899xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011900 xmlSchemaWildcardPtr completeWild,
11901 xmlSchemaWildcardPtr curWild)
11902{
11903 xmlSchemaWildcardNsPtr cur, curB, tmp;
11904
11905 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011906 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000011907 * value.
11908 */
11909 if ((completeWild->any == curWild->any) &&
11910 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
11911 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011912
Daniel Veillard3646d642004-06-02 19:19:14 +000011913 if ((completeWild->negNsSet == NULL) ||
11914 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011915
Daniel Veillard3646d642004-06-02 19:19:14 +000011916 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000011917 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011918
11919 /*
11920 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000011921 */
11922 cur = completeWild->nsSet;
11923 while (cur != NULL) {
11924 found = 0;
11925 curB = curWild->nsSet;
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 break;
11935 cur = cur->next;
11936 }
11937 if (found)
11938 return(0);
11939 } else
11940 return(0);
11941 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011942 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011943 /*
11944 * 2 If either O1 or O2 is any, then any must be the value
11945 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011946 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011947 if (completeWild->any == 0) {
11948 completeWild->any = 1;
11949 if (completeWild->nsSet != NULL) {
11950 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
11951 completeWild->nsSet = NULL;
11952 }
11953 if (completeWild->negNsSet != NULL) {
11954 xmlFree(completeWild->negNsSet);
11955 completeWild->negNsSet = NULL;
11956 }
11957 }
Daniel Veillard50355f02004-06-08 17:52:16 +000011958 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000011959 }
11960 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011961 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000011962 * then the union of those sets must be the value.
11963 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011964 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011965 int found;
11966 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011967
Daniel Veillard3646d642004-06-02 19:19:14 +000011968 cur = curWild->nsSet;
11969 start = completeWild->nsSet;
11970 while (cur != NULL) {
11971 found = 0;
11972 curB = start;
11973 while (curB != NULL) {
11974 if (cur->value == curB->value) {
11975 found = 1;
11976 break;
11977 }
11978 curB = curB->next;
11979 }
11980 if (!found) {
11981 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011982 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000011983 return (-1);
11984 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011985 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000011986 completeWild->nsSet = tmp;
11987 }
11988 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011989 }
11990
Daniel Veillard3646d642004-06-02 19:19:14 +000011991 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011992 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011993 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011994 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000011995 * or ·absent·), then a pair of not and ·absent· must be the value.
11996 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011997 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000011998 (curWild->negNsSet != NULL) &&
11999 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
12000 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000012001
12002 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012003 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012004 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012005 * 5.
12006 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012007 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012008 (completeWild->negNsSet->value != NULL) &&
12009 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012010 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012011 (curWild->negNsSet->value != NULL) &&
12012 (completeWild->nsSet != NULL))) {
12013
12014 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012015
Daniel Veillard3646d642004-06-02 19:19:14 +000012016 if (completeWild->nsSet != NULL) {
12017 cur = completeWild->nsSet;
12018 curB = curWild->negNsSet;
12019 } else {
12020 cur = curWild->nsSet;
12021 curB = completeWild->negNsSet;
12022 }
12023 nsFound = 0;
12024 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012025 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012026 absentFound = 1;
12027 else if (cur->value == curB->value)
12028 nsFound = 1;
12029 if (nsFound && absentFound)
12030 break;
12031 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012032 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012033
12034 if (nsFound && absentFound) {
12035 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012036 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000012037 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012038 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012039 completeWild->any = 1;
12040 if (completeWild->nsSet != NULL) {
12041 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12042 completeWild->nsSet = NULL;
12043 }
12044 if (completeWild->negNsSet != NULL) {
12045 xmlFree(completeWild->negNsSet);
12046 completeWild->negNsSet = NULL;
12047 }
12048 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012049 /*
12050 * 5.2 If the set S includes the negated namespace name
12051 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000012052 * be the value.
12053 */
12054 if (completeWild->nsSet != NULL) {
12055 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12056 completeWild->nsSet = NULL;
12057 }
12058 if (completeWild->negNsSet == NULL) {
12059 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12060 if (completeWild->negNsSet == NULL)
12061 return (-1);
12062 }
12063 completeWild->negNsSet->value = NULL;
12064 } else if ((!nsFound) && absentFound) {
12065 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012066 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012067 * namespace name, then the union is not expressible.
12068 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012069 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012070 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012071 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012072 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012073 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012074 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012075 /*
12076 * 5.4 If the set S does not include either the negated namespace
12077 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012078 * and a namespace name must be the value.
12079 */
12080 if (completeWild->negNsSet == NULL) {
12081 if (completeWild->nsSet != NULL) {
12082 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12083 completeWild->nsSet = NULL;
12084 }
12085 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12086 if (completeWild->negNsSet == NULL)
12087 return (-1);
12088 completeWild->negNsSet->value = curWild->negNsSet->value;
12089 }
12090 }
12091 return (0);
12092 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012093 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012094 * 6.
12095 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012096 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012097 (completeWild->negNsSet->value == NULL) &&
12098 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012099 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012100 (curWild->negNsSet->value == NULL) &&
12101 (completeWild->nsSet != NULL))) {
12102
12103 if (completeWild->nsSet != NULL) {
12104 cur = completeWild->nsSet;
12105 } else {
12106 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012107 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012108 while (cur != NULL) {
12109 if (cur->value == NULL) {
12110 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012111 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012112 * value.
12113 */
12114 completeWild->any = 1;
12115 if (completeWild->nsSet != NULL) {
12116 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12117 completeWild->nsSet = NULL;
12118 }
12119 if (completeWild->negNsSet != NULL) {
12120 xmlFree(completeWild->negNsSet);
12121 completeWild->negNsSet = NULL;
12122 }
12123 return (0);
12124 }
12125 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012126 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012127 if (completeWild->negNsSet == NULL) {
12128 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012129 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012130 * and ·absent· must be the value.
12131 */
12132 if (completeWild->nsSet != NULL) {
12133 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12134 completeWild->nsSet = NULL;
12135 }
12136 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12137 if (completeWild->negNsSet == NULL)
12138 return (-1);
12139 completeWild->negNsSet->value = NULL;
12140 }
12141 return (0);
12142 }
12143 return (0);
12144
12145}
12146
Daniel Veillard50355f02004-06-08 17:52:16 +000012147/**
12148 * xmlSchemaIntersectWildcards:
12149 * @ctxt: the schema parser context
12150 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012151 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012152 *
12153 * Intersects the namespace constraints of the given wildcards.
12154 * @completeWild will hold the resulting intersection.
12155 * Returns a positive error code on failure, -1 in case of an
12156 * internal error, 0 otherwise.
12157 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012158static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012159xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012160 xmlSchemaWildcardPtr completeWild,
12161 xmlSchemaWildcardPtr curWild)
12162{
William M. Brack803812b2004-06-03 02:11:24 +000012163 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012164
12165 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012166 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012167 * value.
12168 */
12169 if ((completeWild->any == curWild->any) &&
12170 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12171 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012172
Daniel Veillard3646d642004-06-02 19:19:14 +000012173 if ((completeWild->negNsSet == NULL) ||
12174 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012175
Daniel Veillard3646d642004-06-02 19:19:14 +000012176 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012177 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012178
12179 /*
12180 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012181 */
12182 cur = completeWild->nsSet;
12183 while (cur != NULL) {
12184 found = 0;
12185 curB = curWild->nsSet;
12186 while (curB != NULL) {
12187 if (cur->value == curB->value) {
12188 found = 1;
12189 break;
12190 }
12191 curB = curB->next;
12192 }
12193 if (!found)
12194 break;
12195 cur = cur->next;
12196 }
12197 if (found)
12198 return(0);
12199 } else
12200 return(0);
12201 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012202 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012203 /*
12204 * 2 If either O1 or O2 is any, then the other must be the value.
12205 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012206 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012207 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012208 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012209 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012210 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012211 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012212 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12213 * name or ·absent·) and the other is a set of (namespace names or
12214 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012215 * the set, minus ·absent· if it was in the set, must be the value.
12216 */
12217 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12218 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12219 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012220
Daniel Veillard3646d642004-06-02 19:19:14 +000012221 if (completeWild->nsSet == NULL) {
12222 neg = completeWild->negNsSet->value;
12223 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12224 return(-1);
12225 } else
12226 neg = curWild->negNsSet->value;
12227 /*
12228 * Remove absent and negated.
12229 */
12230 prev = NULL;
12231 cur = completeWild->nsSet;
12232 while (cur != NULL) {
12233 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012234 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012235 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012236 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012237 prev->next = cur->next;
12238 xmlFree(cur);
12239 break;
12240 }
12241 prev = cur;
12242 cur = cur->next;
12243 }
12244 if (neg != NULL) {
12245 prev = NULL;
12246 cur = completeWild->nsSet;
12247 while (cur != NULL) {
12248 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012249 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012250 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012251 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012252 prev->next = cur->next;
12253 xmlFree(cur);
12254 break;
12255 }
12256 prev = cur;
12257 cur = cur->next;
12258 }
12259 }
12260
12261 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012262 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012263 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012264 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012265 * then the intersection of those sets must be the value.
12266 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012267 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012268 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012269
Daniel Veillard3646d642004-06-02 19:19:14 +000012270 cur = completeWild->nsSet;
12271 prev = NULL;
12272 while (cur != NULL) {
12273 found = 0;
12274 curB = curWild->nsSet;
12275 while (curB != NULL) {
12276 if (cur->value == curB->value) {
12277 found = 1;
12278 break;
12279 }
12280 curB = curB->next;
12281 }
12282 if (!found) {
12283 if (prev == NULL)
12284 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012285 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012286 prev->next = cur->next;
12287 tmp = cur->next;
12288 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012289 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012290 continue;
12291 }
12292 prev = cur;
12293 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012294 }
12295
Daniel Veillard3646d642004-06-02 19:19:14 +000012296 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012297 }
12298 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012299 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012300 */
12301 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012302 (curWild->negNsSet != NULL) &&
12303 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012304 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012305 (curWild->negNsSet->value != NULL)) {
12306
12307 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012308 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012309 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012310 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012311 }
12312 /*
12313 * 6 If the one is a negation of a namespace name and the other
12314 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012315 * of a namespace name must be the value.
12316 */
12317 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12318 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012319 (completeWild->negNsSet->value == NULL)) {
12320 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012321 }
12322 return(0);
12323}
12324
Daniel Veillard50355f02004-06-08 17:52:16 +000012325/**
12326 * xmlSchemaIsWildcardNsConstraintSubset:
12327 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012328 * @sub: the first wildcard
12329 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012330 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012331 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12332 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012333 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012334 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012335 */
12336static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012337xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12338 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012339{
Daniel Veillard50355f02004-06-08 17:52:16 +000012340 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012341 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012342 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012343 if (super->any)
12344 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012345 /*
12346 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12347 * 2.2 super must be a pair of not and the same value.
12348 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012349 if ((sub->negNsSet != NULL) &&
12350 (super->negNsSet != NULL) &&
12351 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012352 return (0);
12353 /*
12354 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012355 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012356 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012357 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012358 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012359 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012360 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012361 xmlSchemaWildcardNsPtr cur, curB;
12362 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012363
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012364 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012365 while (cur != NULL) {
12366 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012367 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012368 while (curB != NULL) {
12369 if (cur->value == curB->value) {
12370 found = 1;
12371 break;
12372 }
12373 curB = curB->next;
12374 }
12375 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012376 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012377 cur = cur->next;
12378 }
12379 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012380 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012381 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012382 xmlSchemaWildcardNsPtr cur;
12383 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012384 * 3.2.2 super must be a pair of not and a namespace name or
12385 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012386 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012387 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012388 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012389 if (cur->value == super->negNsSet->value)
12390 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012391 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012392 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012393 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012394 }
12395 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012396 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012397}
12398
12399/**
12400 * xmlSchemaBuildCompleteAttributeWildcard:
12401 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012402 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012403 * @completeWild: the resulting complete wildcard
12404 *
12405 * Returns -1 in case of an internal error, 0 otherwise.
12406 */
12407static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012408xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012409 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012410 xmlSchemaWildcardPtr *completeWild)
12411{
Daniel Veillard3646d642004-06-02 19:19:14 +000012412 while (attrs != NULL) {
12413 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12414 xmlSchemaAttributeGroupPtr group;
12415
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012416 group = (xmlSchemaAttributeGroupPtr) attrs;
12417 /*
12418 * Handle attribute group references.
12419 */
12420 if (group->ref != NULL) {
12421 if (group->refItem == NULL) {
12422 /*
12423 * TODO: Should we raise a warning here?
12424 */
12425 /*
12426 * The referenced attribute group definition could not
12427 * be resolved beforehand, so skip.
12428 */
12429 attrs = attrs->next;
12430 continue;
12431 } else
12432 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012433 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012434 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012435 * For every attribute group definition, an intersected wildcard
12436 * will be created (assumed that a wildcard exists on the
12437 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012438 * at all).
12439 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12440 * that the intersection will be performed only once.
12441 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012442 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12443 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012444 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012445 group->attributes, &group->attributeWildcard) == -1)
12446 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012447 }
12448 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012449 }
12450 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012451 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012452 /*
12453 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012454 *
12455 * Although the complete wildcard might not correspond to any
12456 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012457 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012458 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12459 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12460 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012461 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012462 completeWild, group->attributeWildcard) == -1)
12463 return (-1);
12464 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012465 (*completeWild)->node = group->attributeWildcard->node;
12466 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012467 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012468 }
12469 }
12470 attrs = attrs->next;
12471 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012472
12473 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012474}
12475
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012476static int
12477xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12478 int *fixed,
12479 const xmlChar **value,
12480 xmlSchemaValPtr *val)
12481{
12482 *fixed = 0;
12483 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012484 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012485 *val = NULL;
12486
12487 if (item->defValue == NULL)
12488 item = item->refDecl;
12489
12490 if (item == NULL)
12491 return (0);
12492
12493 if (item->defValue != NULL) {
12494 *value = item->defValue;
12495 if (val != 0)
12496 *val = item->defVal;
12497 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12498 *fixed = 1;
12499 return (1);
12500 }
12501 return (0);
12502}
Daniel Veillard3646d642004-06-02 19:19:14 +000012503/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012504 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012505 * @wild: the wildcard
12506 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012507 *
12508 * Validation Rule: Wildcard allows Namespace Name
12509 * (cvc-wildcard-namespace)
12510 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012511 *
12512 * Returns 1 if the given namespace matches the wildcard,
12513 * 0 otherwise.
12514 */
12515static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012516xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12517 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012518{
12519 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012520 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012521
12522 if (wild->any)
12523 return(1);
12524 else if (wild->nsSet != NULL) {
12525 xmlSchemaWildcardNsPtr cur;
12526
12527 cur = wild->nsSet;
12528 while (cur != NULL) {
12529 if (xmlStrEqual(cur->value, ns))
12530 return(1);
12531 cur = cur->next;
12532 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012533 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012534 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012535 return(1);
12536
Daniel Veillard3646d642004-06-02 19:19:14 +000012537 return(0);
12538}
12539
12540/**
12541 * xmlSchemaBuildAttributeValidation:
12542 * @ctxt: the schema parser context
12543 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012544 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012545 *
12546 * Builds the wildcard and the attribute uses on the given complex type.
12547 * Returns -1 if an internal error occurs, 0 otherwise.
12548 */
12549static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012550xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12551 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012552{
12553 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012554 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12555 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012556 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012557 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012558 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012559 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012560
Daniel Veillard01fa6152004-06-29 17:04:39 +000012561 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012562 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012563 * Complex Type Definition with complex content Schema Component.
12564 *
12565 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012566 * TODO: Add checks for absent referenced attribute declarations and
12567 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012568 */
12569 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012570 PERROR_INT("xmlSchemaBuildAttributeValidation",
12571 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012572 return (-1);
12573 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012574 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012575 PERROR_INT("xmlSchemaBuildAttributeValidation",
12576 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012577 return (-1);
12578 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012579 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012580 /*
12581 * Inherit the attribute uses of the base type.
12582 */
12583 /*
12584 * NOTE: It is allowed to "extend" the anyType complex type.
12585 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012586 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012587 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012588 for (cur = baseType->attributeUses; cur != NULL;
12589 cur = cur->next) {
12590 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012591 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12592 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012593 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012594 "building attribute uses of complexType", NULL);
12595 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012596 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012597 tmp->attr = cur->attr;
12598 tmp->next = NULL;
12599 if (type->attributeUses == NULL) {
12600 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012601 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012602 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012603 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012604 }
12605 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012606 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012607 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012608 /*
12609 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012610 */
12611 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
12612 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012613 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012614 * NOTE: During the parse time, the wildcard is created on the complexType
12615 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012616 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012617 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012618 PERROR_INT("xmlSchemaBuildAttributeValidation",
12619 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012620 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012621 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012622
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012623 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
12624 ((IS_ANYTYPE(baseType)) ||
12625 ((baseType != NULL) &&
12626 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
12627 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012628 if (type->attributeWildcard != NULL) {
12629 /*
12630 * Union the complete wildcard with the base wildcard.
12631 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012632 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012633 baseType->attributeWildcard) == -1)
12634 return (-1);
12635 } else {
12636 /*
12637 * Just inherit the wildcard.
12638 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012639 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012640 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012641 * wildcard is shared.
12642 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012643 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000012644 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012645 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012646
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012647 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12648 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012649 /*
12650 * Derivation Valid (Restriction, Complex)
12651 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012652 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012653 if (baseType->attributeWildcard == NULL) {
12654 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012655 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012656 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012657 "The type has an attribute wildcard, "
12658 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012659 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012660 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012661 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012662 } else if (xmlSchemaCheckCOSNSSubset(
12663 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012664 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012665 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012666 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012667 NULL, type, NULL,
12668 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012669 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012670 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12671 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012672 return (1);
12673 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012674 /* 4.3 Unless the {base type definition} is the ·ur-type
12675 * definition·, the complex type definition's {attribute
12676 * wildcard}'s {process contents} must be identical to or
12677 * stronger than the {base type definition}'s {attribute
12678 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012679 * than lax is stronger than skip.
12680 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012681 if ((! IS_ANYTYPE(baseType)) &&
12682 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012683 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012684 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012685 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012686 NULL, type, NULL,
12687 "The 'process contents' of the attribute wildcard is "
12688 "weaker than the one in the base type %s",
12689 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012690 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012691 return (1);
12692 }
12693 }
12694 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12695 /*
12696 * Derivation Valid (Extension)
12697 * At this point the type and the base have both, either
12698 * no wildcard or a wildcard.
12699 */
12700 if ((baseType->attributeWildcard != NULL) &&
12701 (baseType->attributeWildcard != type->attributeWildcard)) {
12702 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012703 if (xmlSchemaCheckCOSNSSubset(
12704 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012705 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012706 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012707 NULL, type, NULL,
12708 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012709 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012710 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
12711 FREE_AND_NULL(str)
12712 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012713 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012714 }
12715 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012716
Daniel Veillard3646d642004-06-02 19:19:14 +000012717 /*
12718 * Gather attribute uses defined by this type.
12719 */
12720 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012721 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000012722 &uses, &lastUse) == -1) {
12723 return (-1);
12724 }
12725 }
12726 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012727 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012728 * not have identical {name}s and {target namespace}s."
12729 *
12730 * For "extension" this is done further down.
12731 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012732 if ((uses != NULL) && ((type->flags &
12733 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012734 cur = uses;
12735 while (cur != NULL) {
12736 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012737 while (tmp != NULL) {
12738 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012739 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012740 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012741 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
12742
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012743 xmlSchemaPAttrUseErr(pctxt,
12744 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12745 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012746 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012747 xmlSchemaFormatQName(&str,
12748 xmlSchemaGetAttrTargetNsURI(tmp->attr),
12749 xmlSchemaGetAttrName(tmp->attr)));
12750 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000012751 break;
12752 }
12753 tmp = tmp->next;
12754 }
12755 cur = cur->next;
12756 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012757 }
12758 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012759 /*
12760 * Derive by restriction.
12761 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012762 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012763 type->attributeUses = uses;
12764 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012765 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012766 const xmlChar *bEffValue;
12767 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000012768
12769 cur = uses;
12770 while (cur != NULL) {
12771 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012772 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012773 base = type->attributeUses;
12774 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012775 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012776 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012777 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012778 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012779
12780 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000012781
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012782 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000012783 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12784 (base->attr->occurs ==
12785 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
12786 /*
12787 * NOOP.
12788 */
12789 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012790 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
12791 (base->attr->occurs ==
12792 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012793 /*
12794 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000012795 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012796 xmlSchemaPAttrUseErr(pctxt,
12797 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
12798 type, cur->attr,
12799 "The 'optional' use is inconsistent with a "
12800 "matching 'required' use of the base type",
12801 NULL);
12802 } else if ((cur->attr->occurs ==
12803 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
12804 (base->attr->occurs ==
12805 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
12806 /*
12807 * derivation-ok-restriction 3
12808 */
12809 xmlSchemaPCustomErr(pctxt,
12810 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
12811 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012812 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012813 "attribute use '%s' of the base type is "
12814 "missing",
12815 xmlSchemaFormatQName(&str,
12816 xmlSchemaGetAttrTargetNsURI(base->attr),
12817 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000012818 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012819 } else if (xmlSchemaCheckCOSSTDerivedOK(
12820 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
12821
12822 /*
12823 * SPEC (2.1.2) "R's {attribute declaration}'s
12824 * {type definition} must be validly derived from
12825 * B's {type definition} given the empty set as
12826 * defined in Type Derivation OK (Simple) (§3.14.6)."
12827 */
12828 xmlSchemaPAttrUseErr(pctxt,
12829 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
12830 type, cur->attr,
12831 "The attribute declaration's type "
12832 "definition is not validly derived from "
12833 "the corresponding definition in the "
12834 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000012835 } else {
12836 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012837 * 2.1.3 [Definition:] Let the effective value
12838 * constraint of an attribute use be its {value
12839 * constraint}, if present, otherwise its {attribute
12840 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012841 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012842 xmlSchemaGetEffectiveValueConstraint(base->attr,
12843 &effFixed, &bEffValue, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012844 /*
12845 * 2.1.3 ... one of the following must be true
12846 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012847 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012848 * ·absent· or default.
12849 */
12850 if ((bEffValue != NULL) &&
12851 (effFixed == 1)) {
12852 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012853
12854 xmlSchemaGetEffectiveValueConstraint(base->attr,
12855 &effFixed, &rEffValue, 0);
12856 /*
12857 * 2.1.3.2 R's ·effective value constraint· is
12858 * fixed with the same string as B's.
12859 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012860 */
12861 if ((effFixed == 0) ||
12862 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012863 xmlSchemaPAttrUseErr(pctxt,
12864 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
12865 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012866 "The effective value constraint of the "
12867 "attribute use is inconsistent with "
12868 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012869 NULL);
12870 } else {
12871 /*
12872 * Override the attribute use.
12873 */
12874 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012875 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012876 } else
12877 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000012878 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012879
Daniel Veillard3646d642004-06-02 19:19:14 +000012880 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012881 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012882 base = base->next;
12883 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012884
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012885 if ((!found) && (cur->attr->occurs !=
12886 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
12887 /*
12888 * derivation-ok-restriction 2.2
12889 */
12890 if ((baseType->attributeWildcard == NULL) ||
12891 (xmlSchemaCheckCVCWildcardNamespace(
12892 baseType->attributeWildcard,
12893 cur->attr->targetNamespace) != 1)) {
12894 xmlSchemaPAttrUseErr(pctxt,
12895 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
12896 type, cur->attr,
12897 "Neither a matching attribute use, "
12898 "nor a matching wildcard in the base type does exist",
12899 NULL);
12900 } else {
12901 /*
12902 * Add the attribute use.
12903 *
12904 * Note that this may lead to funny derivation error reports, if
12905 * multiple equal attribute uses exist; but this is not
12906 * allowed anyway, and it will be reported beforehand.
12907 */
12908 tmp = cur;
12909 if (prev != NULL)
12910 prev->next = cur->next;
12911 else
12912 uses = cur->next;
12913 cur = cur->next;
12914 tmp->next = NULL;
12915 if (type->attributeUses == NULL) {
12916 type->attributeUses = tmp;
12917 } else
12918 lastBaseUse->next = tmp;
12919 lastBaseUse = tmp;
12920
12921 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000012922 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012923 }
12924 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000012925 cur = cur->next;
12926 }
12927 if (uses != NULL)
12928 xmlSchemaFreeAttributeUseList(uses);
12929 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012930 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012931 /*
12932 * The spec allows only appending, and not other kinds of extensions.
12933 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012934 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000012935 */
12936 if (uses != NULL) {
12937 if (type->attributeUses == NULL) {
12938 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012939 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000012940 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000012941 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012942 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012943 PERROR_INT("xmlSchemaBuildAttributeValidation",
12944 "no derivation method");
12945 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012946 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012947 /*
12948 * 3.4.6 -> Complex Type Definition Properties Correct
12949 */
12950 if (type->attributeUses != NULL) {
12951 cur = type->attributeUses;
12952 prev = NULL;
12953 while (cur != NULL) {
12954 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012955 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012956 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000012957 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012958 * Note that this was already done for "restriction" and types derived from
12959 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000012960 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012961 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
12962 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012963 while (tmp != NULL) {
12964 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012965 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012966 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000012967 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012968
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012969 xmlSchemaPAttrUseErr(pctxt,
12970 XML_SCHEMAP_CT_PROPS_CORRECT_4,
12971 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012972 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012973 break;
12974 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012975 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000012976 }
12977 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012978 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012979 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000012980 * not have {type definition}s which are or are derived from ID.
12981 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012982 if ((cur->attr->subtypes != NULL) &&
12983 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
12984 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012985 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012986 xmlSchemaPAttrUseErr(pctxt,
12987 XML_SCHEMAP_CT_PROPS_CORRECT_5,
12988 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012989 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012990 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000012991 NULL);
12992 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012993 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012994 id = cur;
12995 }
12996 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012997 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000012998 * stage is to be able to catch dublicate attribute uses. So we had to keep
12999 * prohibited uses in the list as well.
13000 */
13001 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
13002 tmp = cur;
13003 if (prev == NULL)
13004 type->attributeUses = cur->next;
13005 else
13006 prev->next = cur->next;
13007 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000013008 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000013009 } else {
13010 prev = cur;
13011 cur = cur->next;
13012 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013013 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013014 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013015 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013016 * TODO: This check should be removed if we are 100% sure of
13017 * the base type attribute uses already being built.
13018 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013019 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013020 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013021 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013022 PERROR_INT("xmlSchemaBuildAttributeValidation",
13023 "attribute uses not builded on base type");
13024 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013025 return (0);
13026}
13027
13028/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013029 * xmlSchemaTypeFinalContains:
13030 * @schema: the schema
13031 * @type: the type definition
13032 * @final: the final
13033 *
13034 * Evaluates if a type definition contains the given "final".
13035 * This does take "finalDefault" into account as well.
13036 *
13037 * Returns 1 if the type does containt the given "final",
13038 * 0 otherwise.
13039 */
13040static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013041xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013042{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013043 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013044 return (0);
13045 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013046 return (1);
13047 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013048 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013049}
13050
13051/**
13052 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13053 * @type: the Union Simple Type
13054 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013055 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013056 * returns NULL otherwise.
13057 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013058static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013059xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13060{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013061 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013062 if (type->memberTypes != NULL)
13063 return (type->memberTypes);
13064 else
13065 type = type->baseType;
13066 }
13067 return (NULL);
13068}
13069
13070/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013071 * xmlSchemaGetParticleTotalRangeMin:
13072 * @particle: the particle
13073 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013074 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013075 * (all and sequence) + (choice)
13076 *
13077 * Returns the minimun Effective Total Range.
13078 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013079static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013080xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013081{
13082 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013083 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013084 return (0);
13085 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013086 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013087 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013088 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013089
13090 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013091 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013092 while (part != NULL) {
13093 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13094 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013095 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013096 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013097 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013098 if (cur == 0)
13099 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013100 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013101 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013102 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013103 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013104 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013105 } else {
13106 /* <all> and <sequence> */
13107 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013108 xmlSchemaParticlePtr part =
13109 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013110
13111 if (part == NULL)
13112 return (0);
13113 do {
13114 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13115 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013116 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013117 else
13118 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013119 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013120 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013121 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013122 }
13123}
13124
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013125/**
13126 * xmlSchemaGetParticleTotalRangeMax:
13127 * @particle: the particle
13128 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013129 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013130 * (all and sequence) + (choice)
13131 *
13132 * Returns the maximum Effective Total Range.
13133 */
13134static int
13135xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13136{
13137 if ((particle->children == NULL) ||
13138 (particle->children->children == NULL))
13139 return (0);
13140 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13141 int max = -1, cur;
13142 xmlSchemaParticlePtr part =
13143 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013144
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013145 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13146 if (part->children == NULL)
13147 continue;
13148 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13149 (part->children->type == XML_SCHEMA_TYPE_ANY))
13150 cur = part->maxOccurs;
13151 else
13152 cur = xmlSchemaGetParticleTotalRangeMax(part);
13153 if (cur == UNBOUNDED)
13154 return (UNBOUNDED);
13155 if ((max < cur) || (max == -1))
13156 max = cur;
13157 }
13158 /* TODO: Handle overflows? */
13159 return (particle->maxOccurs * max);
13160 } else {
13161 /* <all> and <sequence> */
13162 int sum = 0, cur;
13163 xmlSchemaParticlePtr part =
13164 (xmlSchemaParticlePtr) particle->children->children;
13165
13166 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13167 if (part->children == NULL)
13168 continue;
13169 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13170 (part->children->type == XML_SCHEMA_TYPE_ANY))
13171 cur = part->maxOccurs;
13172 else
13173 cur = xmlSchemaGetParticleTotalRangeMax(part);
13174 if (cur == UNBOUNDED)
13175 return (UNBOUNDED);
13176 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13177 return (UNBOUNDED);
13178 sum += cur;
13179 }
13180 /* TODO: Handle overflows? */
13181 return (particle->maxOccurs * sum);
13182 }
13183}
13184
13185/**
13186 * xmlSchemaIsParticleEmptiable:
13187 * @particle: the particle
13188 *
13189 * Schema Component Constraint: Particle Emptiable
13190 * Checks whether the given particle is emptiable.
13191 *
13192 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013193 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013194static int
13195xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13196{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013197 /*
13198 * SPEC (1) "Its {min occurs} is 0."
13199 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013200 if ((particle == NULL) || (particle->minOccurs == 0) ||
13201 (particle->children == NULL))
13202 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013203 /*
13204 * SPEC (2) "Its {term} is a group and the minimum part of the
13205 * effective total range of that group, [...] is 0."
13206 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013207 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013208 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013209 return (1);
13210 }
13211 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013212}
13213
13214/**
13215 * xmlSchemaCheckCOSSTDerivedOK:
13216 * @type: the derived simple type definition
13217 * @baseType: the base type definition
13218 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013219 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013220 * Type Derivation OK (Simple) (cos-st-derived-OK)
13221 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013222 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013223 * derived from @baseType.
13224 *
13225 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013226 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013227static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013228xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13229 xmlSchemaTypePtr baseType,
13230 int subset)
13231{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013232 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013233 * 1 They are the same type definition.
13234 * TODO: The identy check might have to be more complex than this.
13235 */
13236 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013237 return (0);
13238 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013239 * 2.1 restriction is not in the subset, or in the {final}
13240 * of its own {base type definition};
13241 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013242 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013243 (xmlSchemaTypeFinalContains(type->baseType,
13244 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13245 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013246 }
13247 /* 2.2 */
13248 if (type->baseType == baseType) {
13249 /*
13250 * 2.2.1 D's ·base type definition· is B.
13251 */
13252 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013253 }
13254 /*
13255 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13256 * and is validly derived from B given the subset, as defined by this
13257 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013258 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013259 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013260 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013261 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013262 return (0);
13263 }
13264 /*
13265 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013266 * definition·.
13267 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013268 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013269 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013270 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013271 }
13272 /*
13273 * 2.2.4 B's {variety} is union and D is validly derived from a type
13274 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013275 * defined by this constraint.
13276 *
13277 * NOTE: This seems not to involve built-in types, since there is no
13278 * built-in Union Simple Type.
13279 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013280 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013281 xmlSchemaTypeLinkPtr cur;
13282
13283 cur = baseType->memberTypes;
13284 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013285 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013286 return (0);
13287 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013288 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013289 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013290
Daniel Veillard01fa6152004-06-29 17:04:39 +000013291 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13292}
13293
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013294/**
13295 * xmlSchemaCheckTypeDefCircularInternal:
13296 * @pctxt: the schema parser context
13297 * @ctxtType: the type definition
13298 * @ancestor: an ancestor of @ctxtType
13299 *
13300 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013301 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013302 *
13303 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13304 * circular, 0 otherwise.
13305 */
13306static int
13307xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13308 xmlSchemaTypePtr ctxtType,
13309 xmlSchemaTypePtr ancestor)
13310{
13311 int ret;
13312
13313 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13314 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013315
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013316 if (ctxtType == ancestor) {
13317 xmlSchemaPCustomErr(pctxt,
13318 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13319 NULL, ctxtType, GET_NODE(ctxtType),
13320 "The definition is circular", NULL);
13321 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13322 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013323 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13324 /*
13325 * Avoid inifinite recursion on circular types not yet checked.
13326 */
13327 return (0);
13328 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013329 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13330 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13331 ancestor->baseType);
13332 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13333 return (ret);
13334}
13335
13336/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013337 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013338 * @item: the complex/simple type definition
13339 * @ctxt: the parser context
13340 * @name: the name
13341 *
13342 * Checks for circular type definitions.
13343 */
13344static void
13345xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013346 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013347 const xmlChar * name ATTRIBUTE_UNUSED)
13348{
13349 if ((item == NULL) ||
13350 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13351 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13352 return;
13353 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
13354
13355}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013356
13357/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013358 * xmlSchemaResolveTypeDefs:
13359 * @item: the complex/simple type definition
13360 * @ctxt: the parser context
13361 * @name: the name
13362 *
13363 * Checks for circular type definitions.
13364 */
13365static void
13366xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013367 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013368 const xmlChar * name ATTRIBUTE_UNUSED)
13369{
13370 if (typeDef == NULL)
13371 return;
13372
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013373 /*
13374 * Resolve the base type.
13375 */
13376 if (typeDef->baseType == NULL) {
13377 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13378 typeDef->base, typeDef->baseNs);
13379 if (typeDef->baseType == NULL) {
13380 xmlSchemaPResCompAttrErr(ctxt,
13381 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013382 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013383 "base", typeDef->base, typeDef->baseNs,
13384 XML_SCHEMA_TYPE_SIMPLE, NULL);
13385 return;
13386 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013387 }
13388 if (IS_SIMPLE_TYPE(typeDef)) {
13389 if (VARIETY_UNION(typeDef)) {
13390 /*
13391 * Resolve the memberTypes.
13392 */
13393 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13394 return;
13395 } else if (VARIETY_LIST(typeDef)) {
13396 /*
13397 * Resolve the itemType.
13398 */
13399 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13400 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13401 typeDef->ref, typeDef->refNs);
13402 if ((typeDef->subtypes == NULL) ||
13403 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13404 typeDef->subtypes = NULL;
13405 xmlSchemaPResCompAttrErr(ctxt,
13406 XML_SCHEMAP_SRC_RESOLVE,
13407 typeDef, typeDef->node,
13408 "itemType", typeDef->ref, typeDef->refNs,
13409 XML_SCHEMA_TYPE_SIMPLE, NULL);
13410 }
13411 }
13412 return;
13413 }
13414 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013415}
13416
13417
13418
13419/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013420 * xmlSchemaCheckSTPropsCorrect:
13421 * @ctxt: the schema parser context
13422 * @type: the simple type definition
13423 *
13424 * Checks st-props-correct.
13425 *
13426 * Returns 0 if the properties are correct,
13427 * if not, a positive error code and -1 on internal
13428 * errors.
13429 */
13430static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013431xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013432 xmlSchemaTypePtr type)
13433{
13434 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13435 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013436 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013437
Daniel Veillardc0826a72004-08-10 14:17:33 +000013438 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013439 /*
13440 * Schema Component Constraint: Simple Type Definition Properties Correct
13441 *
13442 * NOTE: This is somehow redundant, since we actually built a simple type
13443 * to have all the needed information; this acts as an self test.
13444 */
13445 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13446 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013447 /* Base type: If the datatype has been ·derived· by ·restriction·
13448 * then the Simple Type Definition component from which it is ·derived·,
13449 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013450 */
13451 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013452 /*
13453 * TODO: Think about: "modulo the impact of Missing
13454 * Sub-components (§5.3)."
13455 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013456 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013457 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013458 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013459 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013460 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013461
Daniel Veillard01fa6152004-06-29 17:04:39 +000013462 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013463 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013464 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013465 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013466 NULL, type, NULL,
13467 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013468 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013469 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013470 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13471 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013472 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13473 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13474 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013475 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013476 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013477 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013478 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013479 "the simple ur-type definition as base type, not '%s'",
13480 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013481 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013482 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13483 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013484 /*
13485 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013486 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013487 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13488 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013489 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013490 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013491 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013492 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013493 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13494 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013495 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013496
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013497 /*
13498 * 3 The {final} of the {base type definition} must not contain restriction.
13499 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013500 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013501 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13502 xmlSchemaPCustomErr(ctxt,
13503 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013504 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013505 "The 'final' of its base type '%s' must not contain "
13506 "'restriction'",
13507 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013508 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013509 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013510 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013511
13512 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013513 * 2 All simple type definitions must be derived ultimately from the ·simple
13514 * ur-type definition (so· circular definitions are disallowed). That is, it
13515 * must be possible to reach a built-in primitive datatype or the ·simple
13516 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013517 *
13518 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013519 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013520 return (0);
13521}
13522
13523/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013524 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013525 * @ctxt: the schema parser context
13526 * @type: the simple type definition
13527 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013528 * Schema Component Constraint:
13529 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13530
13531 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013532 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013533 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013534 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013535 * a positive error code otherwise.
13536 */
13537static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013538xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013539 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013540{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013541 xmlChar *str = NULL;
13542
Daniel Veillard01fa6152004-06-29 17:04:39 +000013543 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013544 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13545 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013546 return (-1);
13547 }
13548
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013549 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013550 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013551 /*
13552 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013553 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013554 */
13555 if (! VARIETY_ATOMIC(type->baseType)) {
13556 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013557 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013558 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013559 "The base type '%s' is not an atomic simple type",
13560 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013561 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013562 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13563 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013564 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013565 * restriction.
13566 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013567 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013568 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013569 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013570 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013571 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013572 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013573 "The final of its base type '%s' must not contain 'restriction'",
13574 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013575 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013576 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
13577 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013578
13579 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013580 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013581 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013582 * Primitive datatypes.
13583 */
13584 if (type->facets != NULL) {
13585 xmlSchemaFacetPtr facet;
13586 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013587
Daniel Veillard01fa6152004-06-29 17:04:39 +000013588 primitive = xmlSchemaGetPrimitiveType(type);
13589 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013590 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13591 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013592 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013593 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013594 facet = type->facets;
13595 do {
13596 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013597 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013598 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013599 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013600 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 }
13602 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013603 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013604 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013605 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013606 }
13607 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013608 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
13609 * of the {base type definition} (call this BF),then the DF's {value}
13610 * must be a valid restriction of BF's {value} as defined in
13611 * [XML Schemas: Datatypes]."
13612 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013613 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013614 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013615 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013616 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013617 xmlSchemaTypePtr itemType = NULL;
13618
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013619 itemType = type->subtypes;
13620 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013621 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13622 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013623 return (-1);
13624 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013625 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013626 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013627 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013628 * 2.1 The {item type definition} must have a {variety} of atomic or
13629 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013630 * must be atomic).
13631 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013632 if ((! VARIETY_ATOMIC(itemType)) &&
13633 (! VARIETY_UNION(itemType))) {
13634 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013635 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013636 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013637 "The item type '%s' does not have a variety of atomic or union",
13638 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013639 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013640 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013641 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013642 xmlSchemaTypeLinkPtr member;
13643
13644 member = itemType->memberTypes;
13645 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013646 if (! VARIETY_ATOMIC(member->type)) {
13647 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013648 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013649 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013650 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013651 "member type '%s' of this item type is not atomic",
13652 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013653 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013654 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
13655 }
13656 member = member->next;
13657 }
13658 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013659
13660 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013661 xmlSchemaFacetPtr facet;
13662 /*
13663 * This is the case if we have: <simpleType><list ..
13664 */
13665 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013666 * 2.3.1
13667 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000013668 * contain list.
13669 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013670 if (xmlSchemaTypeFinalContains(itemType,
13671 XML_SCHEMAS_TYPE_FINAL_LIST)) {
13672 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013673 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013674 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013675 "The final of its item type '%s' must not contain 'list'",
13676 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013677 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013678 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
13679 }
13680 /*
13681 * 2.3.1.2 The {facets} must only contain the whiteSpace
13682 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013683 * OPTIMIZE TODO: the S4S already disallows any facet
13684 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013685 */
13686 if (type->facets != NULL) {
13687 facet = type->facets;
13688 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013689 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013690 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013691 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013692 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013693 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
13694 }
13695 facet = facet->next;
13696 } while (facet != NULL);
13697 }
13698 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013699 * MAYBE TODO: (Hmm, not really) Datatypes states:
13700 * A ·list· datatype can be ·derived· from an ·atomic· datatype
13701 * whose ·lexical space· allows space (such as string or anyURI)or
13702 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000013703 * ·lexical space· allows space.
13704 */
13705 } else {
13706 /*
13707 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013708 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013709 */
13710 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013711 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000013712 * 2.3.2.1 The {base type definition} must have a {variety} of list.
13713 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013714 if (! VARIETY_LIST(type->baseType)) {
13715 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013716 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013717 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013718 "The base type '%s' must be a list type",
13719 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013720 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013721 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
13722 }
13723 /*
13724 * 2.3.2.2 The {final} of the {base type definition} must not
13725 * contain restriction.
13726 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013727 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013728 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013729 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013730 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013731 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013732 "The 'final' of the base type '%s' must not contain 'restriction'",
13733 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013734 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013735 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
13736 }
13737 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013738 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000013739 * from the {base type definition}'s {item type definition} given
13740 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
13741 */
13742 {
13743 xmlSchemaTypePtr baseItemType;
13744
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013745 baseItemType = type->baseType->subtypes;
13746 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013747 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13748 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013749 return (-1);
13750 }
13751 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013752 (xmlSchemaCheckCOSSTDerivedOK(itemType,
13753 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013754 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013755 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013756 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013757 NULL, type, NULL,
13758 "The item type '%s' is not validly derived from "
13759 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013760 xmlSchemaGetComponentQName(&str, itemType),
13761 xmlSchemaGetComponentQName(&strBIT, baseItemType),
13762 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013763
13764 FREE_AND_NULL(str)
13765 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013766 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013767 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
13768 }
13769 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013770
Daniel Veillard01fa6152004-06-29 17:04:39 +000013771 if (type->facets != NULL) {
13772 xmlSchemaFacetPtr facet;
13773 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013774 /*
13775 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000013776 * and enumeration facet components are allowed among the {facets}.
13777 */
13778 facet = type->facets;
13779 do {
13780 switch (facet->type) {
13781 case XML_SCHEMA_FACET_LENGTH:
13782 case XML_SCHEMA_FACET_MINLENGTH:
13783 case XML_SCHEMA_FACET_MAXLENGTH:
13784 case XML_SCHEMA_FACET_WHITESPACE:
13785 /*
13786 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013787 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013788 */
13789 case XML_SCHEMA_FACET_PATTERN:
13790 case XML_SCHEMA_FACET_ENUMERATION:
13791 break;
13792 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013793 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013794 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013795 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013796 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013797 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000013798 * invalid facets.
13799 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013800 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013801 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013802 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013803 facet = facet->next;
13804 } while (facet != NULL);
13805 if (ok == 0)
13806 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
13807 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013808 * SPEC (2.3.2.5) (same as 1.3.2)
13809 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013810 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013811 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013812 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013813 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013814 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013815 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013816 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013817 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000013818 * atomic or list.
13819 */
13820 xmlSchemaTypeLinkPtr member;
13821
13822 member = type->memberTypes;
13823 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013824 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013825 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013826
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013827 if ((! VARIETY_ATOMIC(member->type)) &&
13828 (! VARIETY_LIST(member->type))) {
13829 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013830 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013831 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013832 "The member type '%s' is neither an atomic, nor a list type",
13833 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013834 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013835 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
13836 }
13837 member = member->next;
13838 }
13839 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013840 * 3.3.1 If the {base type definition} is the ·simple ur-type
13841 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000013842 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013843 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013844 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013845 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000013846 * {final} which does not contain union.
13847 */
13848 member = type->memberTypes;
13849 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013850 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013851 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013852 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013853 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013854 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013855 "The 'final' of member type '%s' contains 'union'",
13856 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013857 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013858 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
13859 }
13860 member = member->next;
13861 }
13862 /*
13863 * 3.3.1.2 The {facets} must be empty.
13864 */
13865 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013866 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013867 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013868 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013869 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013870 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
13871 }
13872 } else {
13873 /*
13874 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013875 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013876 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013877 if (! VARIETY_UNION(type->baseType)) {
13878 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013879 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013880 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013881 "The base type '%s' is not a union type",
13882 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013883 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013884 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
13885 }
13886 /*
13887 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
13888 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013889 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013890 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013891 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013892 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013893 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013894 "The 'final' of its base type '%s' must not contain 'restriction'",
13895 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013896 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013897 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
13898 }
13899 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013900 * 3.3.2.3 The {member type definitions}, in order, must be validly
13901 * derived from the corresponding type definitions in the {base
13902 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013903 * as defined in Type Derivation OK (Simple) (§3.14.6).
13904 */
13905 {
13906 xmlSchemaTypeLinkPtr baseMember;
13907
13908 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013909 * OPTIMIZE: if the type is restricting, it has no local defined
13910 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013911 * thus a check for equality can be skipped.
13912 */
13913 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013914 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013915 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000013916 * types of it's base type. This check seems not necessary with
13917 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013918 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013919 */
13920 if (type->memberTypes != NULL) {
13921 member = type->memberTypes;
13922 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013923 if ((member == NULL) && (baseMember != NULL)) {
13924 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13925 "different number of member types in base");
13926 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013927 while (member != NULL) {
13928 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013929 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13930 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013931 }
13932 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013933 (xmlSchemaCheckCOSSTDerivedOK(
13934 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013935 xmlChar *strBMT = NULL, *strBT = NULL;
13936
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013937 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013938 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
13939 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013940 "The member type %s is not validly "
13941 "derived from its corresponding member "
13942 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013943 xmlSchemaGetComponentQName(&str, member->type),
13944 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
13945 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013946 FREE_AND_NULL(str)
13947 FREE_AND_NULL(strBMT)
13948 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013949 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013950 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013951 member = member->next;
13952 baseMember = baseMember->next;
13953 }
13954 }
13955 }
13956 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013957 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000013958 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013959 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013960 if (type->facets != NULL) {
13961 xmlSchemaFacetPtr facet;
13962 int ok = 1;
13963
13964 facet = type->facets;
13965 do {
13966 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
13967 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013968 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013969 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013970 NULL, type, facet);
13971 ok = 0;
13972 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013973 facet = facet->next;
13974 } while (facet != NULL);
13975 if (ok == 0)
13976 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013977
Daniel Veillard01fa6152004-06-29 17:04:39 +000013978 }
13979 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013980 * SPEC (3.3.2.5) (same as 1.3.2)
13981 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013982 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013983 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000013984 */
13985 }
13986 }
13987
13988 return (0);
13989}
13990
13991/**
13992 * xmlSchemaCheckSRCSimpleType:
13993 * @ctxt: the schema parser context
13994 * @type: the simple type definition
13995 *
13996 * Checks crc-simple-type constraints.
13997 *
13998 * Returns 0 if the constraints are satisfied,
13999 * if not a positive error code and -1 on internal
14000 * errors.
14001 */
14002static int
14003xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
14004 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014005{
14006 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014007 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014008 * must satisfy the conditions set out in Constraints on Simple Type
14009 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000014010 */
14011 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
14012 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
14013 /*
14014 * TODO: Removed this, since it got annoying to get an
14015 * extra error report, if anything failed until now.
14016 * Enable this if needed.
14017 */
14018 /*
14019 xmlSchemaPErr(ctxt, type->node,
14020 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014021 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014022 "on simple type definitions.\n",
14023 type->name, NULL);
14024 */
14025 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
14026 }
14027
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014028 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014029 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014030 * src-simple-type.2 If the <restriction> alternative is chosen,
14031 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000014032 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014033 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014034 /*
14035 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014036 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014037 */
14038 } else if (VARIETY_LIST(type)) {
14039 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
14040 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000014041 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014042 *
14043 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014044 */
14045 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014046 xmlSchemaTypeLinkPtr member;
14047 xmlSchemaTypePtr ancestor, anySimpleType;
14048
14049 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14050
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014051 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14052 * the <union> alternative is chosen, there must not be any entries
14053 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000014054 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014055 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014056 member = type->memberTypes;
14057 while (member != NULL) {
14058 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014059 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014060 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014061 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014062 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014063 NULL, type, NULL,
14064 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014065 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014066 }
14067 if (IS_NOT_TYPEFIXED(ancestor))
14068 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014069 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014070 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014071 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014072 * type as item type, which in turn has a list ST as member
14073 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000014074 * was not yet performed.
14075 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014076 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014077
Daniel Veillard01fa6152004-06-29 17:04:39 +000014078 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014079 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014080 member = member->next;
14081 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014082 }
14083
14084 return (0);
14085}
14086
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014087static int
14088xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14089{
14090 if (ctxt->vctxt == NULL) {
14091 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14092 if (ctxt->vctxt == NULL) {
14093 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014094 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014095 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014096 "failed to create a temp. validation context.\n",
14097 NULL, NULL);
14098 return (-1);
14099 }
14100 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014101 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014102 }
14103 return (0);
14104}
14105
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014106static int
14107xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14108 xmlNodePtr node,
14109 xmlSchemaTypePtr type,
14110 const xmlChar *value,
14111 xmlSchemaValPtr *retVal,
14112 int fireErrors,
14113 int normalize,
14114 int isNormalized);
14115
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014116/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014117 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014118 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014119 * @type: the simple type definition
14120 * @value: the default value
14121 * @node: an optional node (the holder of the value)
14122 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014123 * Schema Component Constraint: Element Default Valid (Immediate)
14124 * (cos-valid-default)
14125 * This will be used by the parser only. For the validator there's
14126 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014127 *
14128 * Returns 0 if the constraints are satisfied,
14129 * if not, a positive error code and -1 on internal
14130 * errors.
14131 */
14132static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014133xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14134 xmlNodePtr node,
14135 xmlSchemaTypePtr type,
14136 const xmlChar *value,
14137 xmlSchemaValPtr *val)
14138{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014139 int ret = 0;
14140
14141 /*
14142 * cos-valid-default:
14143 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014144 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014145 * definition the appropriate case among the following must be true:
14146 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014147 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014148 /*
14149 * Complex type.
14150 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014151 * SPEC (2.1) "its {content type} must be a simple type definition
14152 * or mixed."
14153 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014154 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014155 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014156 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014157 if ((! HAS_SIMPLE_CONTENT(type)) &&
14158 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14159 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014160 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014161 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014162 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014163 "For a string to be a valid default, the type definition "
14164 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014165 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014166 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14167 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014168 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014169 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014170 * 1 If the type definition is a simple type definition, then the string
14171 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014172 * Valid (§3.14.4).
14173 *
14174 * AND
14175 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014176 * 2.2.1 If the {content type} is a simple type definition, then the
14177 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014178 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014179 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014180 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014181 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14182 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014183 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014184 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14185 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014186 else
14187 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014188
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014189 if (ret < 0) {
14190 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14191 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014192 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014193
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014194 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014195}
14196
14197/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014198 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014199 * @ctxt: the schema parser context
14200 * @type: the complex type definition
14201 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014202 *.(4.6) Constraints on Complex Type Definition Schema Components
14203 * Schema Component Constraint:
14204 * Complex Type Definition Properties Correct (ct-props-correct)
14205 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014206 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014207 * Returns 0 if the constraints are satisfied, a positive
14208 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014209 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014210static int
14211xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14212 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014213{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014214 /*
14215 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14216 *
14217 * SPEC (1) "The values of the properties of a complex type definition must
14218 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014219 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014220 * Sub-components (§5.3)."
14221 */
14222 if ((type->baseType != NULL) &&
14223 (IS_SIMPLE_TYPE(type->baseType)) &&
14224 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14225 /*
14226 * SPEC (2) "If the {base type definition} is a simple type definition,
14227 * the {derivation method} must be extension."
14228 */
14229 xmlSchemaPCustomErr(pctxt,
14230 XML_SCHEMAP_SRC_CT_1,
14231 NULL, type, NULL,
14232 "If the base type is a simple type, the derivation method must be "
14233 "'extension'", NULL);
14234 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014235 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014236 /*
14237 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14238 * definition·. That is, it must be possible to reach the ·ur-type
14239 * definition by repeatedly following the {base type definition}."
14240 *
14241 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14242 *
14243 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014244 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014245 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14246 * must not have {type definition}s which are or are derived from ID."
14247 *
14248 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14249 */
14250 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014251}
14252
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014253static int
14254xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14255 xmlSchemaTypePtr typeB)
14256{
14257 /*
14258 * TODO: This should implement component-identity
14259 * in the future.
14260 */
14261 if ((typeA == NULL) || (typeB == NULL))
14262 return (0);
14263 return (typeA == typeB);
14264}
14265
14266/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014267 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014268 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014269 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014270 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014271 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014272 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014273 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014274 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14275 *
14276 * STATUS: completed
14277 *
14278 * Returns 0 if the constraints are satisfied, or 1
14279 * if not.
14280 */
14281static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014282xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014283 xmlSchemaTypePtr baseType,
14284 int set)
14285{
14286 int equal = xmlSchemaAreEqualTypes(type, baseType);
14287 /* TODO: Error codes. */
14288 /*
14289 * SPEC "For a complex type definition (call it D, for derived)
14290 * to be validly derived from a type definition (call this
14291 * B, for base) given a subset of {extension, restriction}
14292 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014293 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014294 if (! equal) {
14295 /*
14296 * SPEC (1) "If B and D are not the same type definition, then the
14297 * {derivation method} of D must not be in the subset."
14298 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014299 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014300 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014301 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014302 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014303 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014304 } else {
14305 /*
14306 * SPEC (2.1) "B and D must be the same type definition."
14307 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014308 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014309 }
14310 /*
14311 * SPEC (2.2) "B must be D's {base type definition}."
14312 */
14313 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014314 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014315 /*
14316 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14317 * definition·."
14318 */
14319 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014320 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014321
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014322 if (IS_COMPLEX_TYPE(type->baseType)) {
14323 /*
14324 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14325 * must be validly derived from B given the subset as defined by this
14326 * constraint."
14327 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014328 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014329 baseType, set));
14330 } else {
14331 /*
14332 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14333 * must be validly derived from B given the subset as defined in Type
14334 * Derivation OK (Simple) (§3.14.6).
14335 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014336 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14337 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014338}
14339
14340/**
14341 * xmlSchemaCheckCOSDerivedOK:
14342 * @type: the derived simple type definition
14343 * @baseType: the base type definition
14344 *
14345 * Calls:
14346 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014347 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014348 * Checks wheter @type can be validly derived from @baseType.
14349 *
14350 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014351 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014352static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014353xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014354 xmlSchemaTypePtr baseType,
14355 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014356{
14357 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014358 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014359 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014360 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014361}
14362
William M. Brack2f2a6632004-08-20 23:09:47 +000014363/**
14364 * xmlSchemaCheckCOSCTExtends:
14365 * @ctxt: the schema parser context
14366 * @type: the complex type definition
14367 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014368 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014369 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014370 * Derivation Valid (Extension) (cos-ct-extends)
14371 *
14372 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014373 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014374 * (1.5)
14375 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014376 *
14377 * Returns 0 if the constraints are satisfied, a positive
14378 * error code if not and -1 if an internal error occured.
14379 */
14380static int
14381xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14382 xmlSchemaTypePtr type)
14383{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014384 xmlSchemaTypePtr base = type->baseType;
14385 /*
14386 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14387 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014388 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014389 /*
14390 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014391 * then all of the following must be true:"
14392 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014393 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
14394 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014395 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014396 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014397 */
14398 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14399 xmlSchemaPCustomErr(ctxt,
14400 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14401 NULL, type, NULL,
14402 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014403 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014404 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14405 }
14406 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014407 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014408 * uses}
14409 * of the complex type definition itself, that is, for every attribute
14410 * use in the {attribute uses} of the {base type definition}, there
14411 * must be an attribute use in the {attribute uses} of the complex
14412 * type definition itself whose {attribute declaration} has the same
14413 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014414 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014415 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014416 * NOTE (1.2): This will be already satisfied by the way the attribute
14417 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14418 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014419 */
14420
14421 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014422 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14423 * definition must also have one, and the base type definition's
14424 * {attribute wildcard}'s {namespace constraint} must be a subset
14425 * of the complex type definition's {attribute wildcard}'s {namespace
14426 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014427 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014428 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014429 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014430 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014431 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014432 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014433 if ((type->contentTypeDef != NULL) &&
14434 (type->contentTypeDef == base->contentTypeDef)) {
14435 /*
14436 * SPEC (1.4.1) "The {content type} of the {base type definition}
14437 * and the {content type} of the complex type definition itself
14438 * must be the same simple type definition"
14439 * PASS
14440 */
14441 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14442 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14443 /*
14444 * SPEC (1.4.2) "The {content type} of both the {base type
14445 * definition} and the complex type definition itself must
14446 * be empty."
14447 * PASS
14448 */
14449 } else {
14450 /*
14451 * SPEC (1.4.3) "All of the following must be true:"
14452 */
14453 if (type->subtypes == NULL) {
14454 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014455 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014456 * definition itself must specify a particle.
14457 */
14458 xmlSchemaPCustomErr(ctxt,
14459 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14460 NULL, type, NULL,
14461 "The content type must specify a particle", NULL);
14462 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14463 }
14464 /*
14465 * SPEC (1.4.3.2) "One of the following must be true:"
14466 */
14467 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14468 /*
14469 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14470 * definition} must be empty.
14471 * PASS
14472 */
14473 } else {
14474 /*
14475 * SPEC (1.4.3.2.2) "All of the following must be true:"
14476 */
14477 if ((type->contentType != base->contentType) ||
14478 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14479 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14480 /*
14481 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14482 * or both must be element-only."
14483 */
14484 xmlSchemaPCustomErr(ctxt,
14485 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14486 NULL, type, NULL,
14487 "The content type of both, the type and its base "
14488 "type, must either 'mixed' or 'element-only'", NULL);
14489 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014490 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014491 /*
14492 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14493 * complex type definition must be a ·valid extension·
14494 * of the {base type definition}'s particle, as defined
14495 * in Particle Valid (Extension) (§3.9.6)."
14496 *
14497 * NOTE that we won't check "Particle Valid (Extension)",
14498 * since it is ensured by the derivation process in
14499 * xmlSchemaTypeFixup(). We need to implement this when heading
14500 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014501 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014502 }
14503 /*
14504 * TODO (1.5)
14505 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014506 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014507 } else {
14508 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014509 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014510 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014511 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014512 if (type->contentTypeDef != base) {
14513 /*
14514 * SPEC (2.1) "The {content type} must be the same simple type
14515 * definition."
14516 */
14517 xmlSchemaPCustomErr(ctxt,
14518 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14519 NULL, type, NULL,
14520 "The content type must be the simple base type", NULL);
14521 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14522 }
14523 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14524 /*
14525 * SPEC (2.2) "The {final} of the {base type definition} must not
14526 * contain extension"
14527 * NOTE that this is the same as (1.1).
14528 */
14529 xmlSchemaPCustomErr(ctxt,
14530 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14531 NULL, type, NULL,
14532 "The 'final' of the base type definition "
14533 "contains 'extension'", NULL);
14534 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014535 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014536 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014537 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014538}
14539
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014540/**
14541 * xmlSchemaCheckDerivationOKRestriction:
14542 * @ctxt: the schema parser context
14543 * @type: the complex type definition
14544 *
14545 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014546 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014547 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14548 *
14549 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014550 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014551 * (5.4.2), (5.2.2.1)
14552 *
14553 * Returns 0 if the constraints are satisfied, a positive
14554 * error code if not and -1 if an internal error occured.
14555 */
14556static int
14557xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14558 xmlSchemaTypePtr type)
14559{
14560 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014561
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014562 /*
14563 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14564 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014565 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014566 base = type->baseType;
14567 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14568 /*
14569 * SPEC (1) "The {base type definition} must be a complex type
14570 * definition whose {final} does not contain restriction."
14571 */
14572 xmlSchemaPCustomErr(ctxt,
14573 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14574 NULL, type, NULL,
14575 "The 'final' of the base type definition "
14576 "contains 'restriction'", NULL);
14577 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14578 }
14579 /*
14580 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
14581 *
14582 * SPEC (5) "One of the following must be true:"
14583 */
14584 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
14585 /*
14586 * SPEC (5.1) "The {base type definition} must be the
14587 * ·ur-type definition·."
14588 * PASS
14589 */
14590 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14591 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14592 /*
14593 * SPEC (5.2.1) "The {content type} of the complex type definition
14594 * must be a simple type definition"
14595 *
14596 * SPEC (5.2.2) "One of the following must be true:"
14597 */
14598 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14599 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14600 /*
14601 * SPEC (5.2.2.1) "The {content type} of the {base type
14602 * definition} must be a simple type definition from which
14603 * the {content type} is validly derived given the empty
14604 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
14605 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014606 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014607 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14608 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014609 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014610 /*
14611 * SPEC (5.2.2.2) "The {base type definition} must be mixed
14612 * and have a particle which is ·emptiable· as defined in
14613 * Particle Emptiable (§3.9.6)."
14614 * PASS
14615 */
14616 } else {
14617 xmlSchemaPCustomErr(ctxt,
14618 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14619 NULL, type, NULL,
14620 "The content type of the base type must be either "
14621 "a simple type or 'mixed' and an emptiable particle", NULL);
14622 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14623 }
14624 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14625 /*
14626 * SPEC (5.3.1) "The {content type} of the complex type itself must
14627 * be empty"
14628 */
14629 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14630 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014631 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014632 * definition} must also be empty."
14633 * PASS
14634 */
14635 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
14636 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
14637 xmlSchemaIsParticleEmptiable(
14638 (xmlSchemaParticlePtr) base->subtypes)) {
14639 /*
14640 * SPEC (5.3.2.2) "The {content type} of the {base type
14641 * definition} must be elementOnly or mixed and have a particle
14642 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
14643 * PASS
14644 */
14645 } else {
14646 xmlSchemaPCustomErr(ctxt,
14647 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14648 NULL, type, NULL,
14649 "The content type of the base type must be either "
14650 "empty or 'mixed' (or 'elements-only') and an emptiable "
14651 "particle", NULL);
14652 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14653 }
14654 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014655 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014656 /*
14657 * SPEC (5.4.1.1) "The {content type} of the complex type definition
14658 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014659 */
14660 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
14661 /*
14662 * SPEC (5.4.1.2) "The {content type} of the complex type
14663 * definition itself and of the {base type definition} must be
14664 * mixed"
14665 */
14666 xmlSchemaPCustomErr(ctxt,
14667 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14668 NULL, type, NULL,
14669 "If the content type is 'mixed', then the content type of the "
14670 "base type must also be 'mixed'", NULL);
14671 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14672 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014673 /*
14674 * SPEC (5.4.2) "The particle of the complex type definition itself
14675 * must be a ·valid restriction· of the particle of the {content
14676 * type} of the {base type definition} as defined in Particle Valid
14677 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014678 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014679 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014680 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014681 } else {
14682 xmlSchemaPCustomErr(ctxt,
14683 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14684 NULL, type, NULL,
14685 "The type is not a valid restriction of its base type", NULL);
14686 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14687 }
14688 return (0);
14689}
14690
14691/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014692 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014693 * @ctxt: the schema parser context
14694 * @type: the complex type definition
14695 *
14696 * (3.4.6) Constraints on Complex Type Definition Schema Components
14697 *
14698 * Returns 0 if the constraints are satisfied, a positive
14699 * error code if not and -1 if an internal error occured.
14700 */
14701static int
14702xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
14703 xmlSchemaTypePtr type)
14704{
14705 int ret;
14706 /*
14707 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014708 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014709 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
14710 if (ret != 0)
14711 return (ret);
14712 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
14713 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
14714 else
14715 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
14716 return (ret);
14717}
14718
14719/**
14720 * xmlSchemaCheckSRCCT:
14721 * @ctxt: the schema parser context
14722 * @type: the complex type definition
14723 *
14724 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014725 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014726 * Complex Type Definition Representation OK (src-ct)
14727 *
14728 * Returns 0 if the constraints are satisfied, a positive
14729 * error code if not and -1 if an internal error occured.
14730 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014731static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014732xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014733 xmlSchemaTypePtr type)
14734{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014735 xmlSchemaTypePtr base;
14736 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014737
14738 /*
14739 * TODO: Adjust the error codes here, as I used
14740 * XML_SCHEMAP_SRC_CT_1 only yet.
14741 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014742 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014743 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014744 /*
14745 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014746 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014747 * must be a complex type definition;
14748 */
14749 if (! IS_COMPLEX_TYPE(base)) {
14750 xmlChar *str = NULL;
14751 xmlSchemaPCustomErr(ctxt,
14752 XML_SCHEMAP_SRC_CT_1,
14753 NULL, type, type->node,
14754 "If using <complexContent>, the base type is expected to be "
14755 "a complex type. The base type '%s' is a simple type",
14756 xmlSchemaFormatQName(&str, base->targetNamespace,
14757 base->name));
14758 FREE_AND_NULL(str)
14759 return (XML_SCHEMAP_SRC_CT_1);
14760 }
14761 } else {
14762 /*
14763 * SPEC
14764 * 2 If the <simpleContent> alternative is chosen, all of the
14765 * following must be true:
14766 * 2.1 The type definition ·resolved· to by the ·actual value· of the
14767 * base [attribute] must be one of the following:
14768 */
14769 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014770 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014771 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
14772 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014773 /*
14774 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014775 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014776 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014777 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014778 xmlSchemaPCustomErr(ctxt,
14779 XML_SCHEMAP_SRC_CT_1,
14780 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014781 "If using <simpleContent> and <restriction>, the base "
14782 "type must be a complex type. The base type '%s' is "
14783 "a simple type",
14784 xmlSchemaFormatQName(&str, base->targetNamespace,
14785 base->name));
14786 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014787 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014788 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014789 } else {
14790 /* Base type is a complex type. */
14791 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
14792 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
14793 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014794 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014795 * simple type definition;
14796 * PASS
14797 */
14798 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014799 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014800 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014801 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014802 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014803 type->name);
14804 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014805 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014806 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
14807 (type->flags &
14808 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014809
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014810 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014811 * 2.1.2 only if the <restriction> alternative is also
14812 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014813 * is mixed and a particle emptiable.
14814 */
14815 if (! xmlSchemaIsParticleEmptiable(
14816 (xmlSchemaParticlePtr) base->subtypes)) {
14817 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014818 } else
14819 /*
14820 * Attention: at this point the <simpleType> child is in
14821 * ->contentTypeDef (put there during parsing).
14822 */
14823 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014824 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014825 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014826 * 2.2 If clause 2.1.2 above is satisfied, then there
14827 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014828 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014829 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014830 /* TODO: Change error code to ..._SRC_CT_2_2. */
14831 xmlSchemaPCustomErr(ctxt,
14832 XML_SCHEMAP_SRC_CT_1,
14833 NULL, type, NULL,
14834 "A <simpleType> is expected among the children "
14835 "of <restriction>, if <simpleContent> is used and "
14836 "the base type '%s' is a complex type",
14837 xmlSchemaFormatQName(&str, base->targetNamespace,
14838 base->name));
14839 FREE_AND_NULL(str)
14840 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014841 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014842 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014843 ret = XML_SCHEMAP_SRC_CT_1;
14844 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014845 }
14846 if (ret > 0) {
14847 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014848 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014849 xmlSchemaPCustomErr(ctxt,
14850 XML_SCHEMAP_SRC_CT_1,
14851 NULL, type, NULL,
14852 "If <simpleContent> and <restriction> is used, the "
14853 "base type must be a simple type or a complex type with "
14854 "mixed content and particle emptiable. The base type "
14855 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014856 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014857 base->name));
14858 } else {
14859 xmlSchemaPCustomErr(ctxt,
14860 XML_SCHEMAP_SRC_CT_1,
14861 NULL, type, NULL,
14862 "If <simpleContent> and <extension> is used, the "
14863 "base type must be a simple type. The base type '%s' "
14864 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014865 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014866 base->name));
14867 }
14868 FREE_AND_NULL(str)
14869 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014870 }
14871 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014872 * SPEC (3) "The corresponding complex type definition component must
14873 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014874 * Definition Schema Components (§3.4.6);"
14875 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014876 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014877 /*
14878 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014879 * above for {attribute wildcard} is satisfied, the intensional
14880 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014881 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014882 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014883 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014884 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014885}
William M. Brack2f2a6632004-08-20 23:09:47 +000014886
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014887#ifdef ENABLE_PARTICLE_RESTRICTION
14888/**
14889 * xmlSchemaCheckParticleRangeOK:
14890 * @ctxt: the schema parser context
14891 * @type: the complex type definition
14892 *
14893 * (3.9.6) Constraints on Particle Schema Components
14894 * Schema Component Constraint:
14895 * Occurrence Range OK (range-ok)
14896 *
14897 * STATUS: complete
14898 *
14899 * Returns 0 if the constraints are satisfied, a positive
14900 * error code if not and -1 if an internal error occured.
14901 */
14902static int
14903xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
14904 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014905{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014906 if (rmin < bmin)
14907 return (1);
14908 if ((bmax != UNBOUNDED) &&
14909 (rmax > bmax))
14910 return (1);
14911 return (0);
14912}
14913
14914/**
14915 * xmlSchemaCheckRCaseNameAndTypeOK:
14916 * @ctxt: the schema parser context
14917 * @r: the restricting element declaration particle
14918 * @b: the base element declaration particle
14919 *
14920 * (3.9.6) Constraints on Particle Schema Components
14921 * Schema Component Constraint:
14922 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
14923 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014924 *
14925 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014926 * MISSING (3.2.3)
14927 * CLARIFY: (3.2.2)
14928 *
14929 * Returns 0 if the constraints are satisfied, a positive
14930 * error code if not and -1 if an internal error occured.
14931 */
14932static int
14933xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
14934 xmlSchemaParticlePtr r,
14935 xmlSchemaParticlePtr b)
14936{
14937 xmlSchemaElementPtr elemR, elemB;
14938
14939 /* TODO: Error codes (rcase-NameAndTypeOK). */
14940 elemR = (xmlSchemaElementPtr) r->children;
14941 elemB = (xmlSchemaElementPtr) b->children;
14942 /*
14943 * SPEC (1) "The declarations' {name}s and {target namespace}s are
14944 * the same."
14945 */
14946 if ((elemR != elemB) &&
14947 ((! xmlStrEqual(elemR->name, elemB->name)) ||
14948 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
14949 return (1);
14950 /*
14951 * SPEC (2) "R's occurrence range is a valid restriction of B's
14952 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
14953 */
14954 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
14955 b->minOccurs, b->maxOccurs) != 0)
14956 return (1);
14957 /*
14958 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
14959 * {scope} are global."
14960 */
14961 if (elemR == elemB)
14962 return (0);
14963 /*
14964 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
14965 */
14966 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
14967 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
14968 return (1);
14969 /*
14970 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
14971 * or is not fixed, or R's declaration's {value constraint} is fixed
14972 * with the same value."
14973 */
14974 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
14975 ((elemR->value == NULL) ||
14976 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
14977 /* TODO: Equality of the initial value or normalized or canonical? */
14978 (! xmlStrEqual(elemR->value, elemB->value))))
14979 return (1);
14980 /*
14981 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
14982 * definitions} is a subset of B's declaration's {identity-constraint
14983 * definitions}, if any."
14984 */
14985 if (elemB->idcs != NULL) {
14986 /* TODO */
14987 }
14988 /*
14989 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
14990 * superset of B's declaration's {disallowed substitutions}."
14991 */
14992 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
14993 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
14994 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
14995 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
14996 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
14997 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
14998 return (1);
14999 /*
15000 * SPEC (3.2.5) "R's {type definition} is validly derived given
15001 * {extension, list, union} from B's {type definition}"
15002 *
15003 * BADSPEC TODO: What's the point of adding "list" and "union" to the
15004 * set, if the corresponding constraints handle "restriction" and
15005 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015006 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015007 */
15008 {
15009 int set = 0;
15010
15011 set |= SUBSET_EXTENSION;
15012 set |= SUBSET_LIST;
15013 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015014 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015015 elemB->subtypes, set) != 0)
15016 return (1);
15017 }
15018 return (0);
15019}
15020
15021/**
15022 * xmlSchemaCheckRCaseNSCompat:
15023 * @ctxt: the schema parser context
15024 * @r: the restricting element declaration particle
15025 * @b: the base wildcard particle
15026 *
15027 * (3.9.6) Constraints on Particle Schema Components
15028 * Schema Component Constraint:
15029 * Particle Derivation OK (Elt:Any -- NSCompat)
15030 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015031 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015032 * STATUS: complete
15033 *
15034 * Returns 0 if the constraints are satisfied, a positive
15035 * error code if not and -1 if an internal error occured.
15036 */
15037static int
15038xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
15039 xmlSchemaParticlePtr r,
15040 xmlSchemaParticlePtr b)
15041{
15042 /* TODO:Error codes (rcase-NSCompat). */
15043 /*
15044 * SPEC "For an element declaration particle to be a ·valid restriction·
15045 * of a wildcard particle all of the following must be true:"
15046 *
15047 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15048 * with respect to the wildcard's {namespace constraint} as defined by
15049 * Wildcard allows Namespace Name (§3.10.4)."
15050 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015051 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015052 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15053 return (1);
15054 /*
15055 * SPEC (2) "R's occurrence range is a valid restriction of B's
15056 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15057 */
15058 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15059 b->minOccurs, b->maxOccurs) != 0)
15060 return (1);
15061
15062 return (0);
15063}
15064
15065/**
15066 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15067 * @ctxt: the schema parser context
15068 * @r: the restricting element declaration particle
15069 * @b: the base model group particle
15070 *
15071 * (3.9.6) Constraints on Particle Schema Components
15072 * Schema Component Constraint:
15073 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15074 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015075 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015076 * STATUS: TODO
15077 *
15078 * Returns 0 if the constraints are satisfied, a positive
15079 * error code if not and -1 if an internal error occured.
15080 */
15081static int
15082xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15083 xmlSchemaParticlePtr r,
15084 xmlSchemaParticlePtr b)
15085{
15086 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15087 TODO
15088 return (0);
15089}
15090
15091/**
15092 * xmlSchemaCheckRCaseNSSubset:
15093 * @ctxt: the schema parser context
15094 * @r: the restricting wildcard particle
15095 * @b: the base wildcard particle
15096 *
15097 * (3.9.6) Constraints on Particle Schema Components
15098 * Schema Component Constraint:
15099 * Particle Derivation OK (Any:Any -- NSSubset)
15100 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015101 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015102 * STATUS: complete
15103 *
15104 * Returns 0 if the constraints are satisfied, a positive
15105 * error code if not and -1 if an internal error occured.
15106 */
15107static int
15108xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15109 xmlSchemaParticlePtr r,
15110 xmlSchemaParticlePtr b,
15111 int isAnyTypeBase)
15112{
15113 /* TODO: Error codes (rcase-NSSubset). */
15114 /*
15115 * SPEC (1) "R's occurrence range is a valid restriction of B's
15116 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15117 */
15118 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15119 b->minOccurs, b->maxOccurs))
15120 return (1);
15121 /*
15122 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15123 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15124 */
15125 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15126 (xmlSchemaWildcardPtr) b->children))
15127 return (1);
15128 /*
15129 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15130 * definition·, R's {process contents} must be identical to or stronger
15131 * than B's {process contents}, where strict is stronger than lax is
15132 * stronger than skip."
15133 */
15134 if (! isAnyTypeBase) {
15135 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15136 ((xmlSchemaWildcardPtr) b->children)->processContents)
15137 return (1);
15138 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015139
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015140 return (0);
15141}
15142
15143/**
15144 * xmlSchemaCheckCOSParticleRestrict:
15145 * @ctxt: the schema parser context
15146 * @type: the complex type definition
15147 *
15148 * (3.9.6) Constraints on Particle Schema Components
15149 * Schema Component Constraint:
15150 * Particle Valid (Restriction) (cos-particle-restrict)
15151 *
15152 * STATUS: TODO
15153 *
15154 * Returns 0 if the constraints are satisfied, a positive
15155 * error code if not and -1 if an internal error occured.
15156 */
15157static int
15158xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15159 xmlSchemaParticlePtr r,
15160 xmlSchemaParticlePtr b)
15161{
15162 int ret = 0;
15163
15164 /*part = GET_PARTICLE(type);
15165 basePart = GET_PARTICLE(base);
15166 */
15167
15168 TODO
15169
15170 /*
15171 * SPEC (1) "They are the same particle."
15172 */
15173 if (r == b)
15174 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015175
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015176
15177 return (0);
15178}
15179
15180/**
15181 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15182 * @ctxt: the schema parser context
15183 * @r: the model group particle
15184 * @b: the base wildcard particle
15185 *
15186 * (3.9.6) Constraints on Particle Schema Components
15187 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015188 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015189 * NSRecurseCheckCardinality)
15190 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015191 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015192 * STATUS: TODO: subst-groups
15193 *
15194 * Returns 0 if the constraints are satisfied, a positive
15195 * error code if not and -1 if an internal error occured.
15196 */
15197static int
15198xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15199 xmlSchemaParticlePtr r,
15200 xmlSchemaParticlePtr b)
15201{
15202 xmlSchemaParticlePtr part;
15203 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15204 if ((r->children == NULL) || (r->children->children == NULL))
15205 return (-1);
15206 /*
15207 * SPEC "For a group particle to be a ·valid restriction· of a
15208 * wildcard particle..."
15209 *
15210 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015211 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015212 * Particle Valid (Restriction) (§3.9.6)."
15213 */
15214 part = (xmlSchemaParticlePtr) r->children->children;
15215 do {
15216 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15217 return (1);
15218 part = (xmlSchemaParticlePtr) part->next;
15219 } while (part != NULL);
15220 /*
15221 * SPEC (2) "The effective total range of the group [...] is a
15222 * valid restriction of B's occurrence range as defined by
15223 * Occurrence Range OK (§3.9.6)."
15224 */
15225 if (xmlSchemaCheckParticleRangeOK(
15226 xmlSchemaGetParticleTotalRangeMin(r),
15227 xmlSchemaGetParticleTotalRangeMax(r),
15228 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015229 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015230 return (0);
15231}
15232
15233/**
15234 * xmlSchemaCheckRCaseRecurse:
15235 * @ctxt: the schema parser context
15236 * @r: the <all> or <sequence> model group particle
15237 * @b: the base <all> or <sequence> model group particle
15238 *
15239 * (3.9.6) Constraints on Particle Schema Components
15240 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015241 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015242 Recurse)
15243 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015244 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015245 * STATUS: ?
15246 * TODO: subst-groups
15247 *
15248 * Returns 0 if the constraints are satisfied, a positive
15249 * error code if not and -1 if an internal error occured.
15250 */
15251static int
15252xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15253 xmlSchemaParticlePtr r,
15254 xmlSchemaParticlePtr b)
15255{
15256 /* xmlSchemaParticlePtr part; */
15257 /* TODO: Error codes (rcase-Recurse). */
15258 if ((r->children == NULL) || (b->children == NULL) ||
15259 (r->children->type != b->children->type))
15260 return (-1);
15261 /*
15262 * SPEC "For an all or sequence group particle to be a ·valid
15263 * restriction· of another group particle with the same {compositor}..."
15264 *
15265 * SPEC (1) "R's occurrence range is a valid restriction of B's
15266 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15267 */
15268 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15269 b->minOccurs, b->maxOccurs))
15270 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015271
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015272
15273 return (0);
15274}
15275
15276#endif
15277
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015278#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15279 xmlSchemaPCustomErrExt(pctxt, \
15280 XML_SCHEMAP_INVALID_FACET_VALUE, \
15281 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15282 "It is an error for both '%s' and '%s' to be specified on the "\
15283 "same type definition", \
15284 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15285 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15286
15287#define FACET_RESTR_ERR(fac1, msg) \
15288 xmlSchemaPCustomErr(pctxt, \
15289 XML_SCHEMAP_INVALID_FACET_VALUE, \
15290 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015291 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015292
15293#define FACET_RESTR_FIXED_ERR(fac) \
15294 xmlSchemaPCustomErr(pctxt, \
15295 XML_SCHEMAP_INVALID_FACET_VALUE, \
15296 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15297 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015298 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015299
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015300static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015301xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15302 xmlSchemaFacetPtr facet1,
15303 xmlSchemaFacetPtr facet2,
15304 int lessGreater,
15305 int orEqual,
15306 int ofBase)
15307{
15308 xmlChar *msg = NULL;
15309
15310 msg = xmlStrdup(BAD_CAST "'");
15311 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15312 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15313 if (lessGreater == 0)
15314 msg = xmlStrcat(msg, BAD_CAST " equal to");
15315 if (lessGreater == 1)
15316 msg = xmlStrcat(msg, BAD_CAST " greater than");
15317 else
15318 msg = xmlStrcat(msg, BAD_CAST " less than");
15319
15320 if (orEqual)
15321 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15322 msg = xmlStrcat(msg, BAD_CAST " '");
15323 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15324 if (ofBase)
15325 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15326 else
15327 msg = xmlStrcat(msg, BAD_CAST "'");
15328
15329 xmlSchemaPCustomErr(pctxt,
15330 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015331 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015332 (const char *) msg, NULL);
15333
15334 if (msg != NULL)
15335 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015336}
15337
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015338static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015339xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15340 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015341{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015342 xmlSchemaTypePtr base = type->baseType;
15343 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015344 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015345 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15346 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15347 fmininc = NULL, fmaxinc = NULL,
15348 fminexc = NULL, fmaxexc = NULL,
15349 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15350 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15351 bfmininc = NULL, bfmaxinc = NULL,
15352 bfminexc = NULL, bfmaxexc = NULL;
15353 int res, err = 0, fixedErr;
15354 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015355 * 3 The {facets} of R are the union of S and the {facets}
15356 * of B, eliminating duplicates. To eliminate duplicates,
15357 * when a facet of the same kind occurs in both S and the
15358 * {facets} of B, the one in the {facets} of B is not
15359 * included, with the exception of enumeration and pattern
15360 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015361 * are allowed.
15362 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015363
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015364 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15365 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015366
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015367 last = type->facetSet;
15368 if (last != NULL)
15369 while (last->next != NULL)
15370 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015371
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015372 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15373 facet = cur->facet;
15374 switch (facet->type) {
15375 case XML_SCHEMA_FACET_LENGTH:
15376 flength = facet; break;
15377 case XML_SCHEMA_FACET_MINLENGTH:
15378 fminlen = facet; break;
15379 case XML_SCHEMA_FACET_MININCLUSIVE:
15380 fmininc = facet; break;
15381 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15382 fminexc = facet; break;
15383 case XML_SCHEMA_FACET_MAXLENGTH:
15384 fmaxlen = facet; break;
15385 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15386 fmaxinc = facet; break;
15387 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15388 fmaxexc = facet; break;
15389 case XML_SCHEMA_FACET_TOTALDIGITS:
15390 ftotdig = facet; break;
15391 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15392 ffracdig = facet; break;
15393 default:
15394 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015395 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015396 }
15397 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15398 facet = cur->facet;
15399 switch (facet->type) {
15400 case XML_SCHEMA_FACET_LENGTH:
15401 bflength = facet; break;
15402 case XML_SCHEMA_FACET_MINLENGTH:
15403 bfminlen = facet; break;
15404 case XML_SCHEMA_FACET_MININCLUSIVE:
15405 bfmininc = facet; break;
15406 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15407 bfminexc = facet; break;
15408 case XML_SCHEMA_FACET_MAXLENGTH:
15409 bfmaxlen = facet; break;
15410 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15411 bfmaxinc = facet; break;
15412 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15413 bfmaxexc = facet; break;
15414 case XML_SCHEMA_FACET_TOTALDIGITS:
15415 bftotdig = facet; break;
15416 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15417 bffracdig = facet; break;
15418 default:
15419 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015420 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015421 }
15422 err = 0;
15423 /*
15424 * length and minLength or maxLength (2.2) + (3.2)
15425 */
15426 if (flength && (fminlen || fmaxlen)) {
15427 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15428 "either of 'minLength' or 'maxLength' to be specified on "
15429 "the same type definition")
15430 }
15431 /*
15432 * Mutual exclusions in the same derivation step.
15433 */
15434 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015435 /*
15436 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015437 */
15438 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15439 }
15440 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015441 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015442 * SCC "minInclusive and minExclusive"
15443 */
15444 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015445 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015446
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015447 if (flength && bflength) {
15448 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015449 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015450 * The values have to be equal.
15451 */
15452 res = xmlSchemaCompareValues(flength->val, bflength->val);
15453 if (res == -2)
15454 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015455 if (res != 0)
15456 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15457 if ((res != 0) && (bflength->fixed)) {
15458 FACET_RESTR_FIXED_ERR(flength)
15459 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015460
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015461 }
15462 if (fminlen && bfminlen) {
15463 /*
15464 * SCC "minLength valid restriction"
15465 * minLength >= BASE minLength
15466 */
15467 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15468 if (res == -2)
15469 goto internal_error;
15470 if (res == -1)
15471 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15472 if ((res != 0) && (bfminlen->fixed)) {
15473 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015474 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015475 }
15476 if (fmaxlen && bfmaxlen) {
15477 /*
15478 * SCC "maxLength valid restriction"
15479 * maxLength <= BASE minLength
15480 */
15481 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15482 if (res == -2)
15483 goto internal_error;
15484 if (res == 1)
15485 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15486 if ((res != 0) && (bfmaxlen->fixed)) {
15487 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015488 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015489 }
15490 /*
15491 * SCC "length and minLength or maxLength"
15492 */
15493 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015494 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015495 if (flength) {
15496 if (! fminlen)
15497 flength = bflength;
15498 if (fminlen) {
15499 /* (1.1) length >= minLength */
15500 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15501 if (res == -2)
15502 goto internal_error;
15503 if (res == -1)
15504 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15505 }
15506 if (! fmaxlen)
15507 fmaxlen = bfmaxlen;
15508 if (fmaxlen) {
15509 /* (2.1) length <= maxLength */
15510 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15511 if (res == -2)
15512 goto internal_error;
15513 if (res == 1)
15514 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15515 }
15516 }
15517 if (fmaxinc) {
15518 /*
15519 * "maxInclusive"
15520 */
15521 if (fmininc) {
15522 /* SCC "maxInclusive >= minInclusive" */
15523 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15524 if (res == -2)
15525 goto internal_error;
15526 if (res == -1) {
15527 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15528 }
15529 }
15530 /*
15531 * SCC "maxInclusive valid restriction"
15532 */
15533 if (bfmaxinc) {
15534 /* maxInclusive <= BASE maxInclusive */
15535 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15536 if (res == -2)
15537 goto internal_error;
15538 if (res == 1)
15539 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15540 if ((res != 0) && (bfmaxinc->fixed)) {
15541 FACET_RESTR_FIXED_ERR(fmaxinc)
15542 }
15543 }
15544 if (bfmaxexc) {
15545 /* maxInclusive < BASE maxExclusive */
15546 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15547 if (res == -2)
15548 goto internal_error;
15549 if (res != -1) {
15550 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15551 }
15552 }
15553 if (bfmininc) {
15554 /* maxInclusive >= BASE minInclusive */
15555 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15556 if (res == -2)
15557 goto internal_error;
15558 if (res == -1) {
15559 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15560 }
15561 }
15562 if (bfminexc) {
15563 /* maxInclusive > BASE minExclusive */
15564 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15565 if (res == -2)
15566 goto internal_error;
15567 if (res != 1) {
15568 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15569 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015570 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015571 }
15572 if (fmaxexc) {
15573 /*
15574 * "maxExclusive >= minExclusive"
15575 */
15576 if (fminexc) {
15577 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
15578 if (res == -2)
15579 goto internal_error;
15580 if (res == -1) {
15581 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
15582 }
15583 }
15584 /*
15585 * "maxExclusive valid restriction"
15586 */
15587 if (bfmaxexc) {
15588 /* maxExclusive <= BASE maxExclusive */
15589 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
15590 if (res == -2)
15591 goto internal_error;
15592 if (res == 1) {
15593 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
15594 }
15595 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015596 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015597 }
15598 }
15599 if (bfmaxinc) {
15600 /* maxExclusive <= BASE maxInclusive */
15601 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
15602 if (res == -2)
15603 goto internal_error;
15604 if (res == 1) {
15605 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
15606 }
15607 }
15608 if (bfmininc) {
15609 /* maxExclusive > BASE minInclusive */
15610 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
15611 if (res == -2)
15612 goto internal_error;
15613 if (res != 1) {
15614 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
15615 }
15616 }
15617 if (bfminexc) {
15618 /* maxExclusive > BASE minExclusive */
15619 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
15620 if (res == -2)
15621 goto internal_error;
15622 if (res != 1) {
15623 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
15624 }
15625 }
15626 }
15627 if (fminexc) {
15628 /*
15629 * "minExclusive < maxInclusive"
15630 */
15631 if (fmaxinc) {
15632 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
15633 if (res == -2)
15634 goto internal_error;
15635 if (res != -1) {
15636 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
15637 }
15638 }
15639 /*
15640 * "minExclusive valid restriction"
15641 */
15642 if (bfminexc) {
15643 /* minExclusive >= BASE minExclusive */
15644 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
15645 if (res == -2)
15646 goto internal_error;
15647 if (res == -1) {
15648 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
15649 }
15650 if ((res != 0) && (bfminexc->fixed)) {
15651 FACET_RESTR_FIXED_ERR(fminexc)
15652 }
15653 }
15654 if (bfmaxinc) {
15655 /* minExclusive <= BASE maxInclusive */
15656 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
15657 if (res == -2)
15658 goto internal_error;
15659 if (res == 1) {
15660 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
15661 }
15662 }
15663 if (bfmininc) {
15664 /* minExclusive >= BASE minInclusive */
15665 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
15666 if (res == -2)
15667 goto internal_error;
15668 if (res == -1) {
15669 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
15670 }
15671 }
15672 if (bfmaxexc) {
15673 /* minExclusive < BASE maxExclusive */
15674 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
15675 if (res == -2)
15676 goto internal_error;
15677 if (res != -1) {
15678 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
15679 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015680 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015681 }
15682 if (fmininc) {
15683 /*
15684 * "minInclusive < maxExclusive"
15685 */
15686 if (fmaxexc) {
15687 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
15688 if (res == -2)
15689 goto internal_error;
15690 if (res != -1) {
15691 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
15692 }
15693 }
15694 /*
15695 * "minExclusive valid restriction"
15696 */
15697 if (bfmininc) {
15698 /* minInclusive >= BASE minInclusive */
15699 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
15700 if (res == -2)
15701 goto internal_error;
15702 if (res == -1) {
15703 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
15704 }
15705 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015706 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015707 }
15708 }
15709 if (bfmaxinc) {
15710 /* minInclusive <= BASE maxInclusive */
15711 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
15712 if (res == -2)
15713 goto internal_error;
15714 if (res == -1) {
15715 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
15716 }
15717 }
15718 if (bfminexc) {
15719 /* minInclusive > BASE minExclusive */
15720 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
15721 if (res == -2)
15722 goto internal_error;
15723 if (res != 1)
15724 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
15725 }
15726 if (bfmaxexc) {
15727 /* minInclusive < BASE maxExclusive */
15728 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
15729 if (res == -2)
15730 goto internal_error;
15731 if (res != -1)
15732 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
15733 }
15734 }
15735 if (ftotdig && bftotdig) {
15736 /*
15737 * SCC " totalDigits valid restriction"
15738 * totalDigits <= BASE totalDigits
15739 */
15740 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
15741 if (res == -2)
15742 goto internal_error;
15743 if (res == 1)
15744 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
15745 -1, 1, 1);
15746 if ((res != 0) && (bftotdig->fixed)) {
15747 FACET_RESTR_FIXED_ERR(ftotdig)
15748 }
15749 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015750 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015751 /*
15752 * SCC "fractionDigits valid restriction"
15753 * fractionDigits <= BASE fractionDigits
15754 */
15755 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
15756 if (res == -2)
15757 goto internal_error;
15758 if (res == 1)
15759 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
15760 -1, 1, 1);
15761 if ((res != 0) && (bffracdig->fixed)) {
15762 FACET_RESTR_FIXED_ERR(ffracdig)
15763 }
15764 }
15765 /*
15766 * SCC "fractionDigits less than or equal to totalDigits"
15767 */
15768 if (! ftotdig)
15769 ftotdig = bftotdig;
15770 if (! ffracdig)
15771 ffracdig = bffracdig;
15772 if (ftotdig && ffracdig) {
15773 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
15774 if (res == -2)
15775 goto internal_error;
15776 if (res == 1)
15777 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
15778 -1, 1, 0);
15779 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015780 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015781 * *Enumerations* won' be added here, since only the first set
15782 * of enumerations in the ancestor-or-self axis is used
15783 * for validation, plus we need to use the base type of those
15784 * enumerations for whitespace.
15785 *
15786 * *Patterns*: won't be add here, since they are ORed at
15787 * type level and ANDed at ancestor level. This will
15788 * happed during validation by walking the base axis
15789 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015790 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015791 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15792 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015793 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015794 * Special handling of enumerations and patterns.
15795 * TODO: hmm, they should not appear in the set, so remove this.
15796 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015797 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015798 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015799 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015800 /*
15801 * Search for a duplicate facet in the current type.
15802 */
15803 link = type->facetSet;
15804 err = 0;
15805 fixedErr = 0;
15806 while (link != NULL) {
15807 facet = link->facet;
15808 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015809 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015810 case XML_SCHEMA_FACET_WHITESPACE:
15811 /*
15812 * The whitespace must be stronger.
15813 */
15814 if (facet->whitespace < bfacet->whitespace) {
15815 FACET_RESTR_ERR(flength,
15816 "The 'whitespace' value has to be equal to "
15817 "or stronger than the 'whitespace' value of "
15818 "the base type")
15819 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015820 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015821 (facet->whitespace != bfacet->whitespace)) {
15822 FACET_RESTR_FIXED_ERR(facet)
15823 }
15824 break;
15825 default:
15826 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015827 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015828 /* Duplicate found. */
15829 break;
15830 }
15831 link = link->next;
15832 }
15833 /*
15834 * If no duplicate was found: add the base types's facet
15835 * to the set.
15836 */
15837 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015838 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015839 xmlMalloc(sizeof(xmlSchemaFacetLink));
15840 if (link == NULL) {
15841 xmlSchemaPErrMemory(pctxt,
15842 "deriving facets, creating a facet link", NULL);
15843 return (-1);
15844 }
15845 link->facet = cur->facet;
15846 link->next = NULL;
15847 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015848 type->facetSet = link;
15849 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015850 last->next = link;
15851 last = link;
15852 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015853
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015854 }
15855
15856 return (0);
15857internal_error:
15858 xmlSchemaPCustomErr(pctxt,
15859 XML_SCHEMAP_INVALID_FACET_VALUE,
15860 NULL, type, NULL,
15861 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
15862 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015863}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015864
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015865static int
15866xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
15867 xmlSchemaTypePtr type)
15868{
15869 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
15870 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015871 * The actual value is then formed by replacing any union type
15872 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015873 * {member type definitions}, in order.
15874 */
15875 link = type->memberTypes;
15876 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015877
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015878 if (IS_NOT_TYPEFIXED(link->type))
15879 xmlSchemaTypeFixup(link->type, pctxt, NULL);
15880
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015881 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015882 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015883 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015884 link->type = subLink->type;
15885 if (subLink->next != NULL) {
15886 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015887 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015888 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015889 while (subLink != NULL) {
15890 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015891 xmlMalloc(sizeof(xmlSchemaTypeLink));
15892 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015893 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015894 NULL);
15895 return (-1);
15896 }
15897 newLink->type = subLink->type;
15898 prevLink->next = newLink;
15899 prevLink = newLink;
15900 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015901
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000015902 subLink = subLink->next;
15903 }
15904 }
15905 }
15906 }
15907 link = link->next;
15908 }
15909 return (0);
15910}
15911
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015912static void
15913xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
15914{
15915 int has = 0, needVal = 0, normVal = 0;
15916
15917 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
15918 if (has) {
15919 needVal = (type->baseType->flags &
15920 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
15921 normVal = (type->baseType->flags &
15922 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
15923 }
15924 if (type->facets != NULL) {
15925 xmlSchemaFacetPtr fac;
15926
15927 for (fac = type->facets; fac != NULL; fac = fac->next) {
15928 switch (fac->type) {
15929 case XML_SCHEMA_FACET_WHITESPACE:
15930 break;
15931 case XML_SCHEMA_FACET_PATTERN:
15932 normVal = 1;
15933 has = 1;
15934 break;
15935 case XML_SCHEMA_FACET_ENUMERATION:
15936 needVal = 1;
15937 normVal = 1;
15938 has = 1;
15939 break;
15940 default:
15941 has = 1;
15942 break;
15943 }
15944 }
15945 }
15946 if (normVal)
15947 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
15948 if (needVal)
15949 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15950 if (has)
15951 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
15952
15953 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
15954 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
15955 /*
15956 * OPTIMIZE VAL TODO: Some facets need a computed value.
15957 */
15958 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
15959 (prim->builtInType != XML_SCHEMAS_STRING)) {
15960 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
15961 }
15962 }
15963}
15964
15965static int
15966xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
15967{
15968
15969
15970 /*
15971 * Evaluate the whitespace-facet value.
15972 */
15973 if (VARIETY_LIST(type)) {
15974 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15975 return (0);
15976 } else if (VARIETY_UNION(type))
15977 return (0);
15978
15979 if (type->facetSet != NULL) {
15980 xmlSchemaFacetLinkPtr lin;
15981
15982 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
15983 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
15984 switch (lin->facet->whitespace) {
15985 case XML_SCHEMAS_FACET_PRESERVE:
15986 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
15987 break;
15988 case XML_SCHEMAS_FACET_REPLACE:
15989 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
15990 break;
15991 case XML_SCHEMAS_FACET_COLLAPSE:
15992 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
15993 break;
15994 default:
15995 return (-1);
15996 }
15997 return (0);
15998 }
15999 }
16000 }
16001 /*
16002 * For all ·atomic· datatypes other than string (and types ·derived·
16003 * by ·restriction· from it) the value of whiteSpace is fixed to
16004 * collapse
16005 */
16006 {
16007 xmlSchemaTypePtr anc;
16008
16009 for (anc = type->baseType; anc != NULL &&
16010 anc->builtInType != XML_SCHEMAS_ANYTYPE;
16011 anc = anc->baseType) {
16012
16013 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
16014 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
16015 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
16016
16017 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
16018 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
16019 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
16020
16021 } else
16022 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16023 break;
16024 }
16025 }
16026 return (0);
16027 }
16028 return (0);
16029}
16030
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016031/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016032 * xmlSchemaTypeFixup:
16033 * @typeDecl: the schema type definition
16034 * @ctxt: the schema parser context
16035 *
16036 * Fixes the content model of the type.
16037 */
16038static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016039xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016040 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000016041{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016042 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000016043 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016044 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
16045 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016046 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016047 if (! IS_NOT_TYPEFIXED(type))
16048 return;
16049 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016050 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016051 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016052
16053 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016054 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016055 XML_SCHEMAP_INTERNAL,
16056 NULL, type, NULL,
16057 "Internal error: xmlSchemaTypeFixup, "
16058 "baseType is missing on '%s'", type->name);
16059 return;
16060 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016061
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016062 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016063 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016064
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016065 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016066 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016067 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016068 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016069 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016070 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16071 /*
16072 * Skip fixup if the base type is invalid.
16073 * TODO: Generate a warning!
16074 */
16075 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016076 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016077 /*
16078 * This basically checks if the base type can be derived.
16079 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016080 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016081 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16082 return;
16083 }
16084 /*
16085 * Fixup the content type.
16086 */
16087 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16088 /*
16089 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016090 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016091 if ((IS_COMPLEX_TYPE(baseType)) &&
16092 (baseType->contentTypeDef != NULL) &&
16093 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016094 xmlSchemaTypePtr contentBase, content;
16095 char buf[30];
16096 const xmlChar *tmpname;
16097 /*
16098 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016099 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016100 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016101 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016102 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016103 * SPEC (1.1) "the simple type definition corresponding to the
16104 * <simpleType> among the [children] of <restriction> if there
16105 * is one;"
16106 * Note that this "<simpleType> among the [children]" was put
16107 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016108 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016109 contentBase = type->contentTypeDef;
16110 type->contentTypeDef = NULL;
16111 } else {
16112 /*
16113 * (1.2) "...otherwise (<restriction> has no <simpleType>
16114 * among its [children]), the simple type definition which
16115 * is the {content type} of the ... base type."
16116 */
16117 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016118 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016119 /*
16120 * SPEC
16121 * "... a simple type definition which restricts the simple
16122 * type definition identified in clause 1.1 or clause 1.2
16123 * with a set of facet components"
16124 *
16125 * Create the anonymous simple type, which will be the content
16126 * type of the complex type.
16127 */
16128 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16129 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16130 content = xmlSchemaAddType(pctxt,
16131 pctxt->schema, tmpname, tmpname, type->node);
16132 if (content == NULL)
16133 return;
16134 /*
16135 * We will use the same node as for the <complexType>
16136 * to have it somehow anchored in the schema doc.
16137 */
16138 content->node = type->node;
16139 content->type = XML_SCHEMA_TYPE_SIMPLE;
16140 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16141 content->baseType = contentBase;
16142 /*
16143 * Move the facets, previously anchored on the complexType.
16144 */
16145 content->facets = type->facets;
16146 type->facets = NULL;
16147 content->facetSet = type->facetSet;
16148 type->facetSet = NULL;
16149
16150 type->contentTypeDef = content;
16151 if (IS_NOT_TYPEFIXED(contentBase))
16152 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16153 xmlSchemaTypeFixup(content, pctxt, NULL);
16154
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016155 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16156 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16157 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16158 /*
16159 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16160 * an emptiable particle, then a simple type definition which
16161 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016162 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016163 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016164 (type->contentTypeDef->baseType == NULL)) {
16165 /*
16166 * TODO: Check if this ever happens.
16167 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016168 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016169 XML_SCHEMAP_INTERNAL,
16170 NULL, type, NULL,
16171 "Internal error: xmlSchemaTypeFixup, "
16172 "complex type '%s': the <simpleContent><restriction> "
16173 "is missing a <simpleType> child, but was not catched "
16174 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016175 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016176 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16177 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16178 /*
16179 * SPEC (3) If <extension> + base is <complexType> with
16180 * <simpleType> content, "...then the {content type} of that
16181 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016182 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016183 if (baseType->contentTypeDef == NULL) {
16184 /*
16185 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16186 * should have catched this already.
16187 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016188 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016189 XML_SCHEMAP_INTERNAL,
16190 NULL, type, NULL,
16191 "Internal error: xmlSchemaTypeFixup, "
16192 "complex type '%s': the <extension>ed base type is "
16193 "a complex type with no simple content type",
16194 type->name);
16195 }
16196 type->contentTypeDef = baseType->contentTypeDef;
16197 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16198 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16199 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016200 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016201 * "... then that simple type definition"
16202 */
16203 type->contentTypeDef = baseType;
16204 } else {
16205 /*
16206 * TODO: Check if this ever happens.
16207 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016208 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016209 XML_SCHEMAP_INTERNAL,
16210 NULL, type, NULL,
16211 "Internal error: xmlSchemaTypeFixup, "
16212 "complex type '%s' with <simpleContent>: unhandled "
16213 "derivation case", type->name);
16214 }
16215 } else {
16216 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016217 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016218 (xmlSchemaParticlePtr) type->subtypes;
16219 /*
16220 * Corresponds to <complexType><complexContent>...
16221 *
16222 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016223 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016224 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016225 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016226 * Compute the "effective content":
16227 * (2.1.1) + (2.1.2) + (2.1.3)
16228 */
16229 if ((particle == NULL) ||
16230 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16231 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16232 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16233 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16234 (particle->minOccurs == 0))) &&
16235 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016236 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016237 /*
16238 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16239 * a particle whose properties are as follows:..."
16240 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016241 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016242 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16243 * NOTE that we sill assign it the <complexType> node to
16244 * somehow anchor it in the doc.
16245 */
16246 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016247 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016248 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016249 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016250 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016251 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016252 type->node, 1, 1);
16253 if (particle == NULL)
16254 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016255 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016256 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016257 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016258 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016259 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016260 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16261 if (particle->children == NULL)
16262 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016263
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016264 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016265 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016266 dummySequence = 1;
16267 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16268 } else {
16269 /*
16270 * SPEC (2.1.5) "otherwise empty"
16271 */
16272 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016273 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016274 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016275 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016276 * SPEC (2.2) "otherwise the particle corresponding to the
16277 * <all>, <choice>, <group> or <sequence> among the
16278 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016279 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016280 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16281 }
16282 /*
16283 * Compute the "content type".
16284 */
16285 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016286 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016287 * SPEC (3.1) "If <restriction>..."
16288 * (3.1.1) + (3.1.2) */
16289 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16290 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16291 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16292 }
16293 } else {
16294 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016295 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016296 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016297 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16298 /*
16299 * SPEC (3.2.1)
16300 */
16301 type->contentType = baseType->contentType;
16302 type->subtypes = baseType->subtypes;
16303 /*
16304 * NOTE that the effective mixed is ignored here.
16305 */
16306 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16307 /*
16308 * SPEC (3.2.2)
16309 */
16310 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16311 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16312 } else {
16313 /*
16314 * SPEC (3.2.3)
16315 */
16316 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16317 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16318 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016319 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016320 * {particles} are..."
16321 */
16322 if (! dummySequence) {
16323 xmlSchemaTreeItemPtr effectiveContent =
16324 (xmlSchemaTreeItemPtr) type->subtypes;
16325 /*
16326 * Create the particle.
16327 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016328 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016329 type->node, 1, 1);
16330 if (particle == NULL)
16331 return;
16332 /*
16333 * Create the "sequence" model group.
16334 */
16335 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016336 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016337 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16338 if (particle->children == NULL)
16339 return;
16340 type->subtypes = (xmlSchemaTypePtr) particle;
16341 /*
16342 * SPEC "the particle of the {content type} of
16343 * the ... base ..."
16344 * Create a duplicate of the base type's particle
16345 * and assign its "term" to it.
16346 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016347 particle->children->children =
16348 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16349 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016350 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016351 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016352 if (particle->children->children == NULL)
16353 return;
16354 particle = (xmlSchemaParticlePtr)
16355 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016356 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016357 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16358 /*
16359 * SPEC "followed by the ·effective content·."
16360 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016361 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016362 } else {
16363 /*
16364 * This is the case when there is already an empty
16365 * <sequence> with minOccurs==maxOccurs==1.
16366 * Just add the base types's content type.
16367 * NOTE that, although we miss to add an intermediate
16368 * <sequence>, this should produce no difference to
16369 * neither the regex compilation of the content model,
16370 * nor to the complex type contraints.
16371 */
16372 particle->children->children =
16373 (xmlSchemaTreeItemPtr) baseType->subtypes;
16374 }
16375 }
16376 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016377 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016378 /*
16379 * Apply the complex type component constraints; this will not
16380 * check attributes, since this is done in
16381 * xmlSchemaBuildAttributeValidation().
16382 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016383 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16384 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016385 /*
16386 * Inherit & check constraints for attributes.
16387 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016388 xmlSchemaBuildAttributeValidation(pctxt, type);
16389 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016390 /*
16391 * Simple Type Definition Schema Component
16392 */
16393 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016394 if (VARIETY_LIST(type)) {
16395 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016396 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016397 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016398 if (type->subtypes == NULL) {
16399 /*
16400 * This one is really needed, so get out.
16401 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016402 PERROR_INT("xmlSchemaTypeFixup",
16403 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016404 return;
16405 }
16406 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016407 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16408 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016409 /*
16410 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016411 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016412 if (type->memberTypes == NULL) {
16413 /*
16414 * This one is really needed, so get out.
16415 */
16416 return;
16417 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016418 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016419 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016420 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016421 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016422 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016423 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016424 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016425 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016426 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16427 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016428 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016429 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016430 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016431 */
16432 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016433 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016434 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016435 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16436 /*
16437 * Inherit the itemType.
16438 */
16439 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016440 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016441 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16442 /*
16443 * NOTE that we won't assign the memberTypes of the base,
16444 * since this will make trouble when freeing them; we will
16445 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016446 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016447 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016448 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016449 /*
16450 * Check constraints.
16451 *
16452 * TODO: Split this somehow, we need to know first if we can derive
16453 * from the base type at all!
16454 */
16455 if (type->baseType != NULL) {
16456 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016457 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016458 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016459 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016460 * applied beforehand.
16461 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016462 xmlSchemaCheckSRCSimpleType(pctxt, type);
16463 xmlSchemaCheckFacetValues(type, pctxt);
16464 if ((type->facetSet != NULL) ||
16465 (type->baseType->facetSet != NULL))
16466 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16467 /*
16468 * Whitespace value.
16469 */
16470 xmlSchemaTypeFixupWhitespace(type);
16471 xmlSchemaTypeFixupOptimFacets(type);
16472 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016473 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016474
Daniel Veillard8651f532002-04-17 09:06:27 +000016475#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016476 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016477 xmlGenericError(xmlGenericErrorContext,
16478 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016479 type->node->doc->URL,
16480 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016481 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016482 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016483 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016484 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16485 switch (type->contentType) {
16486 case XML_SCHEMA_CONTENT_SIMPLE:
16487 xmlGenericError(xmlGenericErrorContext, "simple\n");
16488 break;
16489 case XML_SCHEMA_CONTENT_ELEMENTS:
16490 xmlGenericError(xmlGenericErrorContext, "elements\n");
16491 break;
16492 case XML_SCHEMA_CONTENT_UNKNOWN:
16493 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16494 break;
16495 case XML_SCHEMA_CONTENT_EMPTY:
16496 xmlGenericError(xmlGenericErrorContext, "empty\n");
16497 break;
16498 case XML_SCHEMA_CONTENT_MIXED:
16499 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016500 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016501 xmlGenericError(xmlGenericErrorContext,
16502 "mixed as emptiable particle\n");
16503 else
16504 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16505 break;
16506 /* Removed, since not used. */
16507 /*
16508 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16509 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16510 break;
16511 */
16512 case XML_SCHEMA_CONTENT_BASIC:
16513 xmlGenericError(xmlGenericErrorContext, "basic\n");
16514 break;
16515 default:
16516 xmlGenericError(xmlGenericErrorContext,
16517 "not registered !!!\n");
16518 break;
16519 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016520 }
16521#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016522}
16523
16524/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016525 * xmlSchemaCheckFacet:
16526 * @facet: the facet
16527 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016528 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016529 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016530 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016531 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016532 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016533 * Returns 0 if valid, a positive error code if not valid and
16534 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016535 */
16536int
16537xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016538 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016539 xmlSchemaParserCtxtPtr pctxt,
16540 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016541{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016542 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016543
Daniel Veillardce682bc2004-11-05 17:22:25 +000016544 if ((facet == NULL) || (typeDecl == NULL))
16545 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016546 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016547 * TODO: will the parser context be given if used from
16548 * the relaxNG module?
16549 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016550 if (pctxt == NULL)
16551 ctxtGiven = 0;
16552 else
16553 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016554
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016555 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016556 case XML_SCHEMA_FACET_MININCLUSIVE:
16557 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16558 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016559 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16560 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016561 /*
16562 * Okay we need to validate the value
16563 * at that point.
16564 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016565 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016566
16567 /* 4.3.5.5 Constraints on enumeration Schema Components
16568 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016569 * It is an ·error· if any member of {value} is not in the
16570 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016571 *
16572 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016573 * The value ·must· be in the
16574 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016575 */
16576 /*
16577 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016578 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016579 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016580 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016581 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016582 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016583 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016584 */
16585 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
16586 base = typeDecl->baseType;
16587 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016588 PERROR_INT("xmlSchemaCheckFacet",
16589 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016590 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016591 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016592 } else
16593 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016594
16595 if (! ctxtGiven) {
16596 /*
16597 * A context is needed if called from RelaxNG.
16598 */
16599 pctxt = xmlSchemaNewParserCtxt("*");
16600 if (pctxt == NULL)
16601 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000016602 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016603 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016604 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016605 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016606 * facet->node is just the node holding the facet
16607 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016608 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016609 */
16610 ret = xmlSchemaVCheckCVCSimpleType(
16611 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
16612 facet->value, &(facet->val), 1, 1, 0);
16613 if (ret != 0) {
16614 if (ret < 0) {
16615 /* No error message for RelaxNG. */
16616 if (ctxtGiven) {
16617 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16618 XML_SCHEMAP_INTERNAL, facet->node, NULL,
16619 "Internal error: xmlSchemaCheckFacet, "
16620 "failed to validate the value '%s' of the "
16621 "facet '%s' against the base type",
16622 facet->value, xmlSchemaFacetTypeToString(facet->type));
16623 }
16624 goto internal_error;
16625 }
16626 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16627 /* No error message for RelaxNG. */
16628 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016629 xmlChar *str = NULL;
16630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016631 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16632 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016633 "The value '%s' of the facet does not validate "
16634 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016635 facet->value,
16636 xmlSchemaFormatQName(&str,
16637 base->targetNamespace, base->name));
16638 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016639 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016640 goto exit;
16641 } else if (facet->val == NULL) {
16642 if (ctxtGiven) {
16643 PERROR_INT("xmlSchemaCheckFacet",
16644 "value was not computed");
16645 }
16646 TODO
16647 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016648 break;
16649 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016650 case XML_SCHEMA_FACET_PATTERN:
16651 facet->regexp = xmlRegexpCompile(facet->value);
16652 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016653 ret = XML_SCHEMAP_REGEXP_INVALID;
16654 /* No error message for RelaxNG. */
16655 if (ctxtGiven) {
16656 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16657 ret, facet->node, typeDecl,
16658 "The value '%s' of the facet 'pattern' is not a "
16659 "valid regular expression",
16660 facet->value, NULL);
16661 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016662 }
16663 break;
16664 case XML_SCHEMA_FACET_TOTALDIGITS:
16665 case XML_SCHEMA_FACET_FRACTIONDIGITS:
16666 case XML_SCHEMA_FACET_LENGTH:
16667 case XML_SCHEMA_FACET_MAXLENGTH:
16668 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016669 ret = xmlSchemaValidatePredefinedType(
16670 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
16671 facet->value, &(facet->val));
16672 if (ret != 0) {
16673 if (ret < 0) {
16674 /* No error message for RelaxNG. */
16675 if (ctxtGiven) {
16676 PERROR_INT("xmlSchemaCheckFacet",
16677 "validating facet value");
16678 }
16679 goto internal_error;
16680 }
16681 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16682 /* No error message for RelaxNG. */
16683 if (ctxtGiven) {
16684 /* error code */
16685 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16686 ret, facet->node, typeDecl,
16687 "The value '%s' of the facet '%s' is not a valid "
16688 "'nonNegativeInteger'",
16689 facet->value,
16690 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016691 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016692 }
16693 break;
16694 }
16695 case XML_SCHEMA_FACET_WHITESPACE:{
16696 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
16697 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
16698 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
16699 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
16700 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
16701 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
16702 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016703 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
16704 /* No error message for RelaxNG. */
16705 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000016706 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016707 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
16708 ret, facet->node, typeDecl,
16709 "The value '%s' of the facet 'whitespace' is not "
16710 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016711 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016712 }
16713 }
16714 default:
16715 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016716 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016717exit:
16718 if ((! ctxtGiven) && (pctxt != NULL))
16719 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016720 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016721internal_error:
16722 if ((! ctxtGiven) && (pctxt != NULL))
16723 xmlSchemaFreeParserCtxt(pctxt);
16724 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016725}
16726
16727/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016728 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000016729 * @typeDecl: the schema type definition
16730 * @ctxt: the schema parser context
16731 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016732 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000016733 */
16734static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016735xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
16736 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000016737{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016738 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016739 /*
16740 * NOTE: It is intended to use the facets list, instead
16741 * of facetSet.
16742 */
16743 if (typeDecl->facets != NULL) {
16744 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016745
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016746 /*
16747 * Temporarily assign the "schema" to the validation context
16748 * of the parser context. This is needed for NOTATION validation.
16749 */
16750 if (ctxt->vctxt == NULL) {
16751 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
16752 return;
16753 }
16754 ctxt->vctxt->schema = ctxt->schema;
16755
Daniel Veillard01fa6152004-06-29 17:04:39 +000016756 while (facet != NULL) {
16757 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
16758 facet = facet->next;
16759 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000016760
16761 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016762 }
Daniel Veillard4255d502002-04-16 15:50:10 +000016763}
16764
16765/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016766 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016767 * @ctxtMGroup: the searched model group
16768 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016769 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016770 *
16771 * This one is intended to be used by
16772 * xmlSchemaCheckGroupDefCircular only.
16773 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016774 * Returns the particle with the circular model group definition reference,
16775 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016776 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016777static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016778xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016779 xmlSchemaTreeItemPtr particle)
16780{
16781 xmlSchemaTreeItemPtr circ = NULL;
16782 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016783 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016784
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016785 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016786 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016787 if (term == NULL)
16788 continue;
16789 switch (term->type) {
16790 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016791 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016792 if (gdef == groupDef)
16793 return (particle);
16794 /*
16795 * Mark this model group definition to avoid infinite
16796 * recursion on circular references not yet examined.
16797 */
16798 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
16799 continue;
16800 if (gdef->children != NULL) {
16801 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16802 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
16803 gdef->children->children);
16804 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
16805 if (circ != NULL)
16806 return (circ);
16807 }
16808 break;
16809 case XML_SCHEMA_TYPE_SEQUENCE:
16810 case XML_SCHEMA_TYPE_CHOICE:
16811 case XML_SCHEMA_TYPE_ALL:
16812 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
16813 if (circ != NULL)
16814 return (circ);
16815 break;
16816 default:
16817 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016818 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016819 }
16820 return (NULL);
16821}
16822
16823/**
16824 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016825 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016826 * @ctxt: the parser context
16827 * @name: the name
16828 *
16829 * Checks for circular references to model group definitions.
16830 */
16831static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016832xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016833 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016834 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016835{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016836 /*
16837 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016838 * 2 Circular groups are disallowed. That is, within the {particles}
16839 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016840 * is the group itself.
16841 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016842 if ((item == NULL) ||
16843 (item->type != XML_SCHEMA_TYPE_GROUP) ||
16844 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016845 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016846 {
16847 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016848
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016849 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016850 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016851 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016852 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016853 * TODO: The error report is not adequate: this constraint
16854 * is defined for model groups but not definitions, but since
16855 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016856 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016857 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016858 */
16859 xmlSchemaPCustomErr(ctxt,
16860 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016861 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016862 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016863 "defined", xmlSchemaFormatQName(&str,
16864 item->targetNamespace, item->name));
16865 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016866 /*
16867 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016868 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016869 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016870 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016871 }
16872 }
16873}
16874
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016875/**
16876 * xmlSchemaGroupDefTermFixup:
16877 * @item: the particle with a model group definition as term
16878 * @ctxt: the parser context
16879 * @name: the name
16880 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016881 * Checks cos-all-limited.
16882 *
16883 * Assigns the model group of model group definitions to the "term"
16884 * of the referencing particle.
16885 * In xmlSchemaMiscRefFixup the model group definitions was assigned
16886 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016887 */
16888static void
16889xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016890 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016891 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016892{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016893 if ((item == NULL) ||
16894 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
16895 (item->children == NULL) ||
16896 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
16897 (item->children->children == NULL))
16898 return;
16899 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016900 /*
16901 * TODO: Not nice, but we will anchor cos-all-limited here.
16902 */
16903 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
16904 (item->maxOccurs != 1)) {
16905 /*
16906 * SPEC (1.2) "the {term} property of a particle with
16907 * {max occurs}=1which is part of a pair which constitutes the
16908 * {content type} of a complex type definition."
16909 */
16910 xmlSchemaPCustomErr(ctxt,
16911 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
16912 NULL, (xmlSchemaTypePtr) item, item->node,
16913 "The particle's 'maxOccurs' must be 1, since an xs:all model "
16914 "group is its term", NULL);
16915 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016916}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016917
16918/**
16919 * xmlSchemaGetCircAttrGrRef:
16920 * @ctxtGr: the searched attribute group
16921 * @attr: the current attribute list to be processed
16922 *
16923 * This one is intended to be used by
16924 * xmlSchemaCheckSRCAttributeGroupCircular only.
16925 *
16926 * Returns the circular attribute grou reference, otherwise NULL.
16927 */
16928static xmlSchemaAttributeGroupPtr
16929xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
16930 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016931{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016932 xmlSchemaAttributeGroupPtr circ = NULL, gr;
16933 int marked;
16934 /*
16935 * We will search for an attribute group reference which
16936 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016937 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016938 while (attr != NULL) {
16939 marked = 0;
16940 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
16941 gr = (xmlSchemaAttributeGroupPtr) attr;
16942 if (gr->refItem != NULL) {
16943 if (gr->refItem == ctxtGr)
16944 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016945 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016946 XML_SCHEMAS_ATTRGROUP_MARKED) {
16947 attr = attr->next;
16948 continue;
16949 } else {
16950 /*
16951 * Mark as visited to avoid infinite recursion on
16952 * circular references not yet examined.
16953 */
16954 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
16955 marked = 1;
16956 }
16957 }
16958 if (gr->attributes != NULL)
16959 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
16960 /*
16961 * Unmark the visited group's attributes.
16962 */
16963 if (marked)
16964 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
16965 if (circ != NULL)
16966 return (circ);
16967 }
16968 attr = attr->next;
16969 }
16970 return (NULL);
16971}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016972
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016973/**
16974 * xmlSchemaCheckSRCAttributeGroupCircular:
16975 * attrGr: the attribute group definition
16976 * @ctxt: the parser context
16977 * @name: the name
16978 *
16979 * Checks for circular references of attribute groups.
16980 */
16981static void
16982xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016983 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016984 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016985{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016986 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016987 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016988 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016989 * 3 Circular group reference is disallowed outside <redefine>.
16990 * That is, unless this element information item's parent is
16991 * <redefine>, then among the [children], if any, there must
16992 * not be an <attributeGroup> with ref [attribute] which resolves
16993 * to the component corresponding to this <attributeGroup>. Indirect
16994 * circularity is also ruled out. That is, when QName resolution
16995 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
16996 * any <attributeGroup>s with a ref [attribute] among the [children],
16997 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016998 * which resolves to the component corresponding to this <attributeGroup>.
16999 */
17000 /*
17001 * Only global components can be referenced.
17002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017003 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017004 (attrGr->attributes == NULL))
17005 return;
17006 else {
17007 xmlSchemaAttributeGroupPtr circ;
17008
17009 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
17010 if (circ != NULL) {
17011 /*
17012 * TODO: Report the referenced attr group as QName.
17013 */
17014 xmlSchemaPCustomErr(ctxt,
17015 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
17016 NULL, NULL, circ->node,
17017 "Circular reference to the attribute group '%s' "
17018 "defined", attrGr->name);
17019 /*
17020 * NOTE: We will cut the reference to avoid further
17021 * confusion of the processor.
17022 * BADSPEC: The spec should define how to process in this case.
17023 */
17024 circ->attributes = NULL;
17025 circ->refItem = NULL;
17026 }
17027 }
17028}
17029
17030/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000017031 * xmlSchemaAttrGrpFixup:
17032 * @attrgrpDecl: the schema attribute definition
17033 * @ctxt: the schema parser context
17034 * @name: the attribute name
17035 *
17036 * Fixes finish doing the computations on the attributes definitions
17037 */
17038static void
Daniel Veillard3646d642004-06-02 19:19:14 +000017039xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017040 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000017041{
17042 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000017043 name = attrgrp->name;
17044 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017045 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000017046 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017047 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017048
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017049 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017050 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017051 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017052 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017053 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017054 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17055 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017056 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017057 return;
17058 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017059 attrgrp->refItem = ref;
17060 /*
17061 * Check for self reference!
17062 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017063 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017064 attrgrp->attributes = ref->attributes;
17065 attrgrp->attributeWildcard = ref->attributeWildcard;
17066 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017067}
17068
17069/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017070 * xmlSchemaAttrCheckValConstr:
17071 * @item: an schema attribute declaration/use
17072 * @ctxt: a schema parser context
17073 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017074 *
17075 *
17076 * Schema Component Constraint: Attribute Declaration Properties Correct
17077 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017078 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017079 *
17080 * Fixes finish doing the computations on the attributes definitions
17081 */
17082static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017083xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017084 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017085 const xmlChar * name ATTRIBUTE_UNUSED)
17086{
17087
17088 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017089 * 2 if there is a {value constraint}, the canonical lexical
17090 * representation of its value must be ·valid· with respect
17091 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017092 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017093 if (item->defValue != NULL) {
17094 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017095
17096 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017097 PERROR_INT("xmlSchemaCheckAttrValConstr",
17098 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017099 return;
17100 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017101 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17102 item->node, item->subtypes, item->defValue, &(item->defVal),
17103 1, 1, 0);
17104 if (ret != 0) {
17105 if (ret < 0) {
17106 PERROR_INT("xmlSchemaAttrCheckValConstr",
17107 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017108 return;
17109 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017110 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17111 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17112 ret, item->node, (xmlSchemaTypePtr) item,
17113 "The value of the value constraint is not valid", NULL, NULL);
17114 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017115 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017116 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017117}
17118
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017119static xmlSchemaElementPtr
17120xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17121 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017122{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017123 xmlSchemaElementPtr ret;
17124
17125 if (SUBST_GROUP_AFF(ancestor) == NULL)
17126 return (NULL);
17127 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17128 return (ancestor);
17129
17130 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17131 return (NULL);
17132 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17133 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17134 SUBST_GROUP_AFF(ancestor));
17135 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17136
17137 return (ret);
17138}
17139
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017140/**
17141 * xmlSchemaCheckElemPropsCorrect:
17142 * @ctxt: a schema parser context
17143 * @decl: the element declaration
17144 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017145 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017146 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017147 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017148 *
17149 * STATUS:
17150 * missing: (6)
17151 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017152static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017153xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17154 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017155{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017156 int ret = 0;
17157 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017158 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017159 * SPEC (1) "The values of the properties of an element declaration
17160 * must be as described in the property tableau in The Element
17161 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17162 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017163 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017164 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017165 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017166
17167 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017168 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017169 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017170 * affiliation}, then {scope} must be global."
17171 */
17172 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17173 xmlSchemaPCustomErr(pctxt,
17174 XML_SCHEMAP_E_PROPS_CORRECT_3,
17175 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17176 "Only global element declarations can have a "
17177 "substitution group affiliation", NULL);
17178 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017179 }
17180 /*
17181 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17182 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017183 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017184 * property."
17185 */
17186 if (head == elemDecl)
17187 circ = head;
17188 else if (SUBST_GROUP_AFF(head) != NULL)
17189 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17190 else
17191 circ = NULL;
17192 if (circ != NULL) {
17193 xmlChar *strA = NULL, *strB = NULL;
17194
17195 xmlSchemaPCustomErrExt(pctxt,
17196 XML_SCHEMAP_E_PROPS_CORRECT_6,
17197 NULL, (xmlSchemaTypePtr) circ, circ->node,
17198 "The element declaration '%s' defines a circular "
17199 "substitution group to element declaration '%s'",
17200 xmlSchemaGetComponentQName(&strA, circ),
17201 xmlSchemaGetComponentQName(&strB, head),
17202 NULL);
17203 FREE_AND_NULL(strA)
17204 FREE_AND_NULL(strB)
17205 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17206 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017207 /*
17208 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017209 * the {type definition}
17210 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017211 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017212 * of the {substitution group exclusions} of the {substitution group
17213 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17214 * (if the {type definition} is complex) or as defined in
17215 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017216 * simple)."
17217 *
17218 * NOTE: {substitution group exclusions} means the values of the
17219 * attribute "final".
17220 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017221
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017222 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017223 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017224
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017225 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17226 set |= SUBSET_EXTENSION;
17227 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17228 set |= SUBSET_RESTRICTION;
17229
17230 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17231 ELEM_TYPE(head), set) != 0) {
17232 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17233
17234 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017235 xmlSchemaPCustomErrExt(pctxt,
17236 XML_SCHEMAP_E_PROPS_CORRECT_4,
17237 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017238 "The type definition '%s' was "
17239 "either rejected by the substitution group "
17240 "affiliation '%s', or not validly derived from its type "
17241 "definition '%s'",
17242 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017243 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017244 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017245 FREE_AND_NULL(strA)
17246 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017247 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017248 }
17249 }
17250 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017251 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017252 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017253 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017254 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017255 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017256 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017257 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017258 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017259 ((IS_SIMPLE_TYPE(typeDef) &&
17260 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017261 (IS_COMPLEX_TYPE(typeDef) &&
17262 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017263 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17264 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017265
17266 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17267 xmlSchemaPCustomErr(pctxt,
17268 XML_SCHEMAP_E_PROPS_CORRECT_5,
17269 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17270 "The type definition (or type definition's content type) is or "
17271 "is derived from ID; value constraints are not allowed in "
17272 "conjunction with such a type definition", NULL);
17273 } else if (elemDecl->value != NULL) {
17274 int vcret;
17275 xmlNodePtr node = NULL;
17276
17277 /*
17278 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17279 * representation of its value must be ·valid· with respect to the
17280 * {type definition} as defined in Element Default Valid (Immediate)
17281 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017282 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017283 if (typeDef == NULL) {
17284 xmlSchemaPErr(pctxt, elemDecl->node,
17285 XML_SCHEMAP_INTERNAL,
17286 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17287 "type is missing... skipping validation of "
17288 "the value constraint", NULL, NULL);
17289 return (-1);
17290 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017291 if (elemDecl->node != NULL) {
17292 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17293 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17294 BAD_CAST "fixed");
17295 else
17296 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17297 BAD_CAST "default");
17298 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017299 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17300 typeDef, elemDecl->value, &(elemDecl->defVal));
17301 if (vcret != 0) {
17302 if (vcret < 0) {
17303 PERROR_INT("xmlSchemaElemCheckValConstr",
17304 "failed to validate the value constraint of an "
17305 "element declaration");
17306 return (-1);
17307 }
17308 return (vcret);
17309 }
17310 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017311
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017312 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017313}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017314
17315/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017316 * xmlSchemaCheckElemSubstGroup:
17317 * @ctxt: a schema parser context
17318 * @decl: the element declaration
17319 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017320 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017321 * Schema Component Constraint:
17322 * Substitution Group (cos-equiv-class)
17323 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017324 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017325 * a list will be built for each subst. group head, holding all direct
17326 * referents to this head.
17327 * NOTE that this function needs:
17328 * 1. circular subst. groups to be checked beforehand
17329 * 2. the declaration's type to be derived from the head's type
17330 *
17331 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017332 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017333 */
17334static void
17335xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17336 xmlSchemaElementPtr elemDecl)
17337{
17338 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17339 /* SPEC (1) "Its {abstract} is false." */
17340 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17341 return;
17342 {
17343 xmlSchemaElementPtr head;
17344 xmlSchemaTypePtr headType, type;
17345 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017346 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017347 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17348 * {disallowed substitutions} as the blocking constraint, as defined in
17349 * Substitution Group OK (Transitive) (§3.3.6)."
17350 */
17351 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17352 head = SUBST_GROUP_AFF(head)) {
17353 set = 0;
17354 methSet = 0;
17355 /*
17356 * The blocking constraints.
17357 */
17358 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17359 continue;
17360 headType = head->subtypes;
17361 type = elemDecl->subtypes;
17362 if (headType == type)
17363 goto add_member;
17364 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17365 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17366 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17367 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17368 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017369 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017370 * "The set of all {derivation method}s involved in the
17371 * derivation of D's {type definition} from C's {type definition}
17372 * does not intersect with the union of the blocking constraint,
17373 * C's {prohibited substitutions} (if C is complex, otherwise the
17374 * empty set) and the {prohibited substitutions} (respectively the
17375 * empty set) of any intermediate {type definition}s in the
17376 * derivation of D's {type definition} from C's {type definition}."
17377 */
17378 /*
17379 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17380 * subst.head axis, the methSet does not need to be computed for
17381 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017382 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017383 /*
17384 * The set of all {derivation method}s involved in the derivation
17385 */
17386 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017387 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017388 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17389 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17390 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017391
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017392 if ((type->flags &
17393 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17394 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17395 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17396
17397 type = type->baseType;
17398 }
17399 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017400 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017401 * the head's type.
17402 */
17403 type = elemDecl->subtypes->baseType;
17404 while (type != NULL) {
17405 if (IS_COMPLEX_TYPE(type)) {
17406 if ((type->flags &
17407 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17408 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17409 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17410 if ((type->flags &
17411 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17412 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17413 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17414 } else
17415 break;
17416 if (type == headType)
17417 break;
17418 type = type->baseType;
17419 }
17420 if ((set != 0) &&
17421 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17422 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17423 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17424 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17425 continue;
17426 }
17427add_member:
17428 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17429 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17430 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17431 }
17432 }
17433}
17434
17435/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017436 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017437 * @item: an schema element declaration/particle
17438 * @ctxt: a schema parser context
17439 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017440 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017441 * Validates the value constraints of an element declaration.
17442 *
17443 * Fixes finish doing the computations on the element declarations.
17444 */
17445static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017446xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017447 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017448 const xmlChar * name ATTRIBUTE_UNUSED)
17449{
17450 if (elemDecl == NULL)
17451 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017452 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17453 return;
17454 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017455 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17456 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017457}
17458
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017459/**
17460 * xmlSchemaMiscRefFixup:
17461 * @item: an schema component
17462 * @ctxt: a schema parser context
17463 * @name: the internal name of the component
17464 *
17465 * Resolves references of misc. schema components.
17466 */
17467static void
17468xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017469 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017470 const xmlChar * name ATTRIBUTE_UNUSED)
17471{
17472 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017473 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017474 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17475 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17476 xmlSchemaTreeItemPtr refItem;
17477 /*
17478 * Resolve the reference.
17479 */
17480 item->children = NULL;
17481 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17482 ref->itemType, ref->name, ref->targetNamespace);
17483 if (refItem == NULL) {
17484 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017485 NULL, GET_NODE(item), "ref", ref->name,
17486 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017487 } else {
17488 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17489 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017490 * NOTE that we will assign the model group definition
17491 * itself to the "term" of the particle. This will ease
17492 * the check for circular model group definitions. After
17493 * that the "term" will be assigned the model group of the
17494 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017495 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017496 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017497 } else
17498 item->children = refItem;
17499 }
17500 }
17501 }
17502}
17503
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017504static int
17505xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17506 xmlSchemaValPtr y)
17507{
17508 xmlSchemaTypePtr tx, ty, ptx, pty;
17509 int ret;
17510
17511 while (x != NULL) {
17512 /* Same types. */
17513 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17514 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17515 ptx = xmlSchemaGetPrimitiveType(tx);
17516 pty = xmlSchemaGetPrimitiveType(ty);
17517 /*
17518 * (1) if a datatype T' is ·derived· by ·restriction· from an
17519 * atomic datatype T then the ·value space· of T' is a subset of
17520 * the ·value space· of T. */
17521 /*
17522 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17523 * from a common atomic ancestor T then the ·value space·s of T'
17524 * and T'' may overlap.
17525 */
17526 if (ptx != pty)
17527 return(0);
17528 /*
17529 * We assume computed values to be normalized, so do a fast
17530 * string comparison for string based types.
17531 */
17532 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17533 IS_ANY_SIMPLE_TYPE(ptx)) {
17534 if (! xmlStrEqual(
17535 xmlSchemaValueGetAsString(x),
17536 xmlSchemaValueGetAsString(y)))
17537 return (0);
17538 } else {
17539 ret = xmlSchemaCompareValuesWhtsp(
17540 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17541 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17542 if (ret == -2)
17543 return(-1);
17544 if (ret != 0)
17545 return(0);
17546 }
17547 /*
17548 * Lists.
17549 */
17550 x = xmlSchemaValueGetNext(x);
17551 if (x != NULL) {
17552 y = xmlSchemaValueGetNext(y);
17553 if (y == NULL)
17554 return (0);
17555 } else if (xmlSchemaValueGetNext(y) != NULL)
17556 return (0);
17557 else
17558 return (1);
17559 }
17560 return (0);
17561}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017562
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017563/**
17564 * xmlSchemaAttrFixup:
17565 * @item: an schema attribute declaration/use.
17566 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017567 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017568 *
17569 * Fixes finish doing the computations on attribute declarations/uses.
17570 */
17571static void
17572xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017573 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017574 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017575{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017576 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017577 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017578 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000017579 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000017580 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017581 * The simple type definition corresponding to the <simpleType> element
17582 * information item in the [children], if present, otherwise the simple
17583 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000017584 * [attribute], if present, otherwise the ·simple ur-type definition·.
17585 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017586 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000017587 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017588 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
17589 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017590 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017591 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017592 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000017593
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017594 type = xmlSchemaGetType(ctxt->schema, item->typeName,
17595 item->typeNs);
17596 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017597 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017598 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017599 (xmlSchemaTypePtr) item, item->node,
17600 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017601 XML_SCHEMA_TYPE_SIMPLE, NULL);
17602 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017603 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017604
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017605 } else if (item->ref != NULL) {
17606 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000017607
Daniel Veillardc0826a72004-08-10 14:17:33 +000017608 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017609 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017610 * attribute declaration.
17611 */
17612 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017613 * TODO: Evaluate, what errors could occur if the declaration is not
17614 * found. It might be possible that the "typefixup" might crash if
17615 * no ref declaration was found.
17616 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017617 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017618 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000017619 xmlSchemaPResCompAttrErr(ctxt,
17620 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017621 (xmlSchemaTypePtr) item, item->node,
17622 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017623 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017624 return;
17625 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017626 item->refDecl = decl;
17627 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017628 item->subtypes = decl->subtypes;
17629 /*
17630 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017631 * au-props-correct.2: If the {attribute declaration} has a fixed
17632 * {value constraint}, then if the attribute use itself has a
17633 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017634 * that of the {attribute declaration}'s {value constraint}.
17635 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017636 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017637 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017638 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017639 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017640 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17641 NULL, NULL, item->node,
17642 "The attribute declaration has a 'fixed' value constraint "
17643 ", thus it must be 'fixed' in attribute use as well",
17644 NULL);
17645 } else {
17646 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
17647 xmlSchemaPCustomErr(ctxt,
17648 XML_SCHEMAP_AU_PROPS_CORRECT_2,
17649 NULL, NULL, item->node,
17650 "The 'fixed' value constraint of the attribute use "
17651 "must match the attribute declaration's value "
17652 "constraint '%s'",
17653 decl->defValue);
17654 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017655 }
17656 /*
17657 * FUTURE: One should change the values of the attr. use
17658 * if ever validation should be attempted even if the
17659 * schema itself was not fully valid.
17660 */
17661 }
Daniel Veillard3646d642004-06-02 19:19:14 +000017662 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017663 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
17664 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017665}
17666
17667/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017668 * xmlSchemaResolveIDCKeyRef:
17669 * @idc: the identity-constraint definition
17670 * @ctxt: the schema parser context
17671 * @name: the attribute name
17672 *
17673 * Resolve keyRef references to key/unique IDCs.
17674 */
17675static void
17676xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017677 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000017678 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017679{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017680 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
17681 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017682 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017683 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017684 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017685 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017686 idc->ref->targetNamespace);
17687 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017688 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017689 * TODO: It is actually not an error to fail to resolve.
17690 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017691 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017692 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017693 (xmlSchemaTypePtr) idc, idc->node,
17694 "refer", idc->ref->name,
17695 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017696 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
17697 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000017698 } else {
17699 if (idc->nbFields !=
17700 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
17701 xmlChar *str = NULL;
17702 xmlSchemaIDCPtr refer;
17703
17704 refer = (xmlSchemaIDCPtr) idc->ref->item;
17705 /*
17706 * SPEC c-props-correct(2)
17707 * "If the {identity-constraint category} is keyref,
17708 * the cardinality of the {fields} must equal that of
17709 * the {fields} of the {referenced key}.
17710 */
17711 xmlSchemaPCustomErr(pctxt,
17712 XML_SCHEMAP_C_PROPS_CORRECT,
17713 NULL, (xmlSchemaTypePtr) idc, idc->node,
17714 "The cardinality of the keyref differs from the "
17715 "cardinality of the referenced key '%s'",
17716 xmlSchemaFormatQName(&str, refer->targetNamespace,
17717 refer->name)
17718 );
17719 FREE_AND_NULL(str)
17720 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017721 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017722 }
17723}
17724
17725/**
Daniel Veillard4255d502002-04-16 15:50:10 +000017726 * xmlSchemaParse:
17727 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017728 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017729 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000017730 * XML Shema struture which can be used to validate instances.
17731 * *WARNING* this interface is highly subject to change
17732 *
17733 * Returns the internal XML Schema structure built from the resource or
17734 * NULL in case of error
17735 */
17736xmlSchemaPtr
17737xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
17738{
17739 xmlSchemaPtr ret = NULL;
17740 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017741 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017742 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017743
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017744 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017745 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017746 * the API; i.e. not automatically by the validated instance document.
17747 */
17748
Daniel Veillard4255d502002-04-16 15:50:10 +000017749 xmlSchemaInitTypes();
17750
Daniel Veillard6045c902002-10-09 21:13:59 +000017751 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000017752 return (NULL);
17753
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017754 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000017755 ctxt->counter = 0;
17756 ctxt->container = NULL;
17757
17758 /*
17759 * First step is to parse the input document into an DOM/Infoset
17760 */
Daniel Veillard6045c902002-10-09 21:13:59 +000017761 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017762 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017763 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017764 if (doc == NULL) {
17765 xmlSchemaPErr(ctxt, NULL,
17766 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017767 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017768 ctxt->URL, NULL);
17769 return (NULL);
17770 }
Daniel Veillard6045c902002-10-09 21:13:59 +000017771 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017772 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
17773 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017774 if (doc == NULL) {
17775 xmlSchemaPErr(ctxt, NULL,
17776 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017777 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017778 NULL, NULL);
17779 return (NULL);
17780 }
17781 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000017782 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000017783 } else if (ctxt->doc != NULL) {
17784 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017785 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000017786 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017787 xmlSchemaPErr(ctxt, NULL,
17788 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017789 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017790 NULL, NULL);
17791 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000017792 }
17793
17794 /*
17795 * Then extract the root and Schema parse it
17796 */
17797 root = xmlDocGetRootElement(doc);
17798 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017799 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
17800 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017801 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000017802 if (!preserve) {
17803 xmlFreeDoc(doc);
17804 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017805 return (NULL);
17806 }
17807
17808 /*
17809 * Remove all the blank text nodes
17810 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000017811 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000017812
17813 /*
17814 * Then do the parsing for good
17815 */
17816 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000017817 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000017818 if (!preserve) {
17819 xmlFreeDoc(doc);
17820 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017821 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000017822 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017823 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000017824 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000017825 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000017826 ctxt->ctxtType = NULL;
17827 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017828
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017829 /*
17830 * Resolve base types of simple/complex types.
17831 */
17832 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017833
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017834 if (ctxt->nberrors != 0)
17835 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017836
17837 if (ret->volatiles != NULL) {
17838 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17839 int i;
17840 xmlSchemaTreeItemPtr item;
17841
17842 for (i = 0; i < list->nbItems; i++) {
17843 item = (xmlSchemaTreeItemPtr) list->items[i];
17844 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17845 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017846 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017847 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017848 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000017849 * Then fixup all attributes declarations
17850 */
17851 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017852 /*
17853 * Then fixup all attributes group declarations
17854 */
17855 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
17856 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000017857 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017858 * Resolve identity-constraint keyRefs.
17859 */
17860 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017861 /*
17862 * Check type defnitions for circular references.
17863 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017864 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017865 xmlSchemaCheckTypeDefCircular, ctxt);
17866 /*
17867 * Check model groups defnitions for circular references.
17868 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017869 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017870 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017871 /*
17872 * Set the "term" of particles pointing to model group definitions
17873 * to the contained model group.
17874 */
17875 if (ret->volatiles != NULL) {
17876 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
17877 int i;
17878 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017879
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017880 for (i = 0; i < list->nbItems; i++) {
17881 item = (xmlSchemaParticlePtr) list->items[i];
17882 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
17883 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
17884 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017885 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017886 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017887 * Check attribute groups for circular references.
17888 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017889 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
17890 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017891 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000017892 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017893 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000017894 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017895 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017896 /*
17897 * We will stop here if the schema was not valid to avoid internal errors
17898 * on missing sub-components. This is not conforming to the spec, since it
17899 * allows missing components, but it might make further processing crash.
17900 * So see it as a very strict handling, which might be made more lax in the
17901 * future.
17902 */
17903 if (ctxt->nberrors != 0)
17904 goto exit;
17905 /*
17906 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017907 */
17908 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017909 /*
17910 * Validate the value constraint of attribute declarations/uses.
17911 */
17912 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017913 /*
17914 * Validate the value constraint of element declarations.
17915 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017916 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017917
17918 if (ctxt->nberrors != 0)
17919 goto exit;
17920
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017921 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017922 * TODO: cos-element-consistent, cos-all-limited
17923 *
17924 * Then build the content model for all complex types
17925 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017926 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017927 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017928
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000017929exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017930 if (ctxt->nberrors != 0) {
17931 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017932 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000017933 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017934 return (ret);
17935}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017936
Daniel Veillard4255d502002-04-16 15:50:10 +000017937/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000017938 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000017939 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000017940 * @err: the error callback
17941 * @warn: the warning callback
17942 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000017943 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000017944 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000017945 */
17946void
17947xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017948 xmlSchemaValidityErrorFunc err,
17949 xmlSchemaValidityWarningFunc warn, void *ctx)
17950{
Daniel Veillard4255d502002-04-16 15:50:10 +000017951 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017952 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000017953 ctxt->error = err;
17954 ctxt->warning = warn;
17955 ctxt->userData = ctx;
17956}
17957
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017958/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000017959 * xmlSchemaGetParserErrors:
17960 * @ctxt: a XMl-Schema parser context
17961 * @err: the error callback result
17962 * @warn: the warning callback result
17963 * @ctx: contextual data for the callbacks result
17964 *
17965 * Get the callback information used to handle errors for a parser context
17966 *
17967 * Returns -1 in case of failure, 0 otherwise
17968 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017969int
Daniel Veillard259f0df2004-08-18 09:13:18 +000017970xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
17971 xmlSchemaValidityErrorFunc * err,
17972 xmlSchemaValidityWarningFunc * warn, void **ctx)
17973{
17974 if (ctxt == NULL)
17975 return(-1);
17976 if (err != NULL)
17977 *err = ctxt->error;
17978 if (warn != NULL)
17979 *warn = ctxt->warning;
17980 if (ctx != NULL)
17981 *ctx = ctxt->userData;
17982 return(0);
17983}
17984
17985/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017986 * xmlSchemaFacetTypeToString:
17987 * @type: the facet type
17988 *
17989 * Convert the xmlSchemaTypeType to a char string.
17990 *
17991 * Returns the char string representation of the facet type if the
17992 * type is a facet and an "Internal Error" string otherwise.
17993 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017994static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000017995xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
17996{
17997 switch (type) {
17998 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017999 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018000 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018001 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018002 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018003 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018004 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018005 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018006 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018007 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018008 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018009 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018010 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018011 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018012 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018013 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018014 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018015 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018016 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018017 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018018 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018019 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018020 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018021 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018022 default:
18023 break;
18024 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018025 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018026}
18027
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018028static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000018029xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
18030{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018031 /*
18032 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000018033 * from xsd:string.
18034 */
18035 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018036 /*
18037 * Note that we assume a whitespace of preserve for anySimpleType.
18038 */
18039 if ((type->builtInType == XML_SCHEMAS_STRING) ||
18040 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
18041 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000018042 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018043 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018044 else {
18045 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018046 * For all ·atomic· datatypes other than string (and types ·derived·
18047 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000018048 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018049 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018050 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018051 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018052 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018053 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018054 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018055 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018056 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018057 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
18058 } else if (VARIETY_UNION(type)) {
18059 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
18060 } else if (VARIETY_ATOMIC(type)) {
18061 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
18062 return (XML_SCHEMA_WHITESPACE_PRESERVE);
18063 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
18064 return (XML_SCHEMA_WHITESPACE_REPLACE);
18065 else
18066 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018067 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018068 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018069}
18070
Daniel Veillard4255d502002-04-16 15:50:10 +000018071/************************************************************************
18072 * *
18073 * Simple type validation *
18074 * *
18075 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018076
Daniel Veillard4255d502002-04-16 15:50:10 +000018077
18078/************************************************************************
18079 * *
18080 * DOM Validation code *
18081 * *
18082 ************************************************************************/
18083
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018084static void
18085xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18086{
18087 int i, nbItems;
18088 xmlSchemaTypePtr item, *items;
18089
18090
18091 /*
18092 * During the Assemble of the schema ctxt->curItems has
18093 * been filled with the relevant new items. Fix those up.
18094 */
18095 nbItems = ctxt->assemble->nbItems;
18096 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018097
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018098 for (i = 0; i < nbItems; i++) {
18099 item = items[i];
18100 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018101 case XML_SCHEMA_TYPE_COMPLEX:
18102 case XML_SCHEMA_TYPE_SIMPLE:
18103 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18104 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018105 case XML_SCHEMA_TYPE_ATTRIBUTE:
18106 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18107 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018108 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018109 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018110 ctxt, NULL);
18111 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018112 case XML_SCHEMA_TYPE_PARTICLE:
18113 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018114 break;
18115 case XML_SCHEMA_TYPE_IDC_KEY:
18116 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18117 case XML_SCHEMA_TYPE_IDC_KEYREF:
18118 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18119 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018120 default:
18121 break;
18122 }
18123 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018124 if (ctxt->nberrors != 0)
18125 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018126 /*
18127 * Circularity checks.
18128 */
18129 for (i = 0; i < nbItems; i++) {
18130 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018131 switch (item->type) {
18132 case XML_SCHEMA_TYPE_COMPLEX:
18133 case XML_SCHEMA_TYPE_SIMPLE:
18134 xmlSchemaCheckTypeDefCircular(
18135 (xmlSchemaTypePtr) item, ctxt, NULL);
18136 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018137 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018138 xmlSchemaCheckGroupDefCircular(
18139 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018140 break;
18141 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18142 xmlSchemaCheckAttributeGroupCircular(
18143 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18144 break;
18145 default:
18146 break;
18147 }
18148 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018149 if (ctxt->nberrors != 0)
18150 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018151 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018152 * Set the "term" of particles pointing to model group definitions
18153 * to the contained model group.
18154 */
18155 for (i = 0; i < nbItems; i++) {
18156 item = items[i];
18157 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18158 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018159 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018160 XML_SCHEMA_TYPE_GROUP)) {
18161 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18162 ctxt, NULL);
18163 }
18164 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018165 if (ctxt->nberrors != 0)
18166 return;
18167 for (i = 0; i < nbItems; i++) {
18168 item = items[i];
18169 switch (item->type) {
18170 case XML_SCHEMA_TYPE_ELEMENT:
18171 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18172 NULL, NULL, NULL);
18173 break;
18174 default:
18175 break;
18176 }
18177 }
18178 if (ctxt->nberrors != 0)
18179 return;
18180
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018181 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018182 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018183 */
18184 for (i = 0; i < nbItems; i++) {
18185 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018186 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018187 case XML_SCHEMA_TYPE_SIMPLE:
18188 case XML_SCHEMA_TYPE_COMPLEX:
18189 xmlSchemaTypeFixup(item, ctxt, NULL);
18190 break;
18191 default:
18192 break;
18193 }
18194 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018195 if (ctxt->nberrors != 0)
18196 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018197 /*
18198 * Validate value contraint values.
18199 */
18200 for (i = 0; i < nbItems; i++) {
18201 item = items[i];
18202 switch (item->type) {
18203 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018204 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18205 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018206 break;
18207 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018208 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018209 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018210 break;
18211 default:
18212 break;
18213 }
18214 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018215 if (ctxt->nberrors != 0)
18216 return;
18217 /*
18218 * Build the content model for complex types.
18219 */
18220 for (i = 0; i < nbItems; i++) {
18221 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018222 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018223 case XML_SCHEMA_TYPE_COMPLEX:
18224 xmlSchemaBuildContentModel(item, ctxt, NULL);
18225 break;
18226 default:
18227 break;
18228 }
18229 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018230}
18231
18232/**
18233 * xmlSchemaAssembleByLocation:
18234 * @pctxt: a schema parser context
18235 * @vctxt: a schema validation context
18236 * @schema: the existing schema
18237 * @node: the node that fired the assembling
18238 * @nsName: the namespace name of the new schema
18239 * @location: the location of the schema
18240 *
18241 * Expands an existing schema by an additional schema.
18242 *
18243 * Returns 0 if the new schema is correct, a positive error code
18244 * number otherwise and -1 in case of an internal or API error.
18245 */
18246static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018247xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018248 xmlSchemaPtr schema,
18249 xmlNodePtr node,
18250 const xmlChar *nsName,
18251 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018252{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018253 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018254 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018255 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018256 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018257 xmlSchemaParserCtxtPtr pctxt;
18258
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018259 /*
18260 * This should be used:
18261 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018262 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018263 * 3. if requested via the API
18264 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018265 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018266 return (-1);
18267 /*
18268 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018269 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018270 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018271 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18272 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018273 pctxt = vctxt->pctxt;
18274 /*
18275 * Set the counter to produce unique names for anonymous items.
18276 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018277 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018278 /*
18279 * Acquire the schema document.
18280 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018281 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18282 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018283 if (ret != 0) {
18284 if (doc != NULL)
18285 xmlFreeDoc(doc);
18286 } else if (doc != NULL) {
18287 docElem = xmlDocGetRootElement(doc);
18288 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018289 * Create new assemble info.
18290 */
18291 if (pctxt->assemble == NULL) {
18292 pctxt->assemble = xmlSchemaNewAssemble();
18293 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018294 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018295 "Memory error: xmlSchemaAssembleByLocation, "
18296 "allocating assemble info", NULL);
18297 xmlFreeDoc(doc);
18298 return (-1);
18299 }
18300 }
18301 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018302 * Save and reset the context & schema.
18303 */
18304 oldflags = schema->flags;
18305 oldtns = schema->targetNamespace;
18306 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018307 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018308
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018309 xmlSchemaClearSchemaDefaults(schema);
18310 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018311 if ((targetNs != NULL) &&
18312 xmlStrEqual(targetNs, xmlSchemaNs)) {
18313 /*
18314 * We are parsing the schema for schema!
18315 */
18316 vctxt->pctxt->isS4S = 1;
18317 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018318 /* schema->nbCurItems = 0; */
18319 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018320 pctxt->ctxtType = NULL;
18321 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018322
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018323 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18324 if (pctxt->nberrors != 0) {
18325 vctxt->nberrors += pctxt->nberrors;
18326 goto finally;
18327 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018328 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018329 if (pctxt->nberrors != 0) {
18330 vctxt->nberrors += pctxt->nberrors;
18331 goto finally;
18332 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018333 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018334 if (pctxt->nberrors != 0)
18335 vctxt->nberrors += pctxt->nberrors;
18336finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018337 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018338 * Set the counter of items.
18339 */
18340 schema->counter = pctxt->counter;
18341 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018342 * Free the list of assembled components.
18343 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018344 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018345 /*
18346 * Restore the context & schema.
18347 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018348 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018349 schema->flags = oldflags;
18350 schema->targetNamespace = oldtns;
18351 schema->doc = olddoc;
18352 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018353 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018354 return (ret);
18355}
18356
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018357static xmlSchemaAttrInfoPtr
18358xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18359 int metaType)
18360{
18361 if (vctxt->nbAttrInfos == 0)
18362 return (NULL);
18363 {
18364 int i;
18365 xmlSchemaAttrInfoPtr iattr;
18366
18367 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18368 iattr = vctxt->attrInfos[i];
18369 if (iattr->metaType == metaType)
18370 return (iattr);
18371 }
18372
18373 }
18374 return (NULL);
18375}
18376
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018377/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018378 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018379 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018380 *
18381 * Expands an existing schema by an additional schema using
18382 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18383 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18384 * must be set to 1.
18385 *
18386 * Returns 0 if the new schema is correct, a positive error code
18387 * number otherwise and -1 in case of an internal or API error.
18388 */
18389static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018390xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018391{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018392 const xmlChar *cur, *end;
18393 const xmlChar *nsname = NULL, *location;
18394 int count = 0;
18395 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018396 xmlSchemaAttrInfoPtr iattr;
18397
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018398 /*
18399 * Parse the value; we will assume an even number of values
18400 * to be given (this is how Xerces and XSV work).
18401 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018402 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18403 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18404 if (iattr == NULL)
18405 xmlSchemaGetMetaAttrInfo(vctxt,
18406 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18407 if (iattr == NULL)
18408 return (0);
18409 cur = iattr->value;
18410 do {
18411 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018412 /*
18413 * Get the namespace name.
18414 */
18415 while (IS_BLANK_CH(*cur))
18416 cur++;
18417 end = cur;
18418 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18419 end++;
18420 if (end == cur)
18421 break;
18422 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018423 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018424 cur = end;
18425 }
18426 /*
18427 * Get the URI.
18428 */
18429 while (IS_BLANK_CH(*cur))
18430 cur++;
18431 end = cur;
18432 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18433 end++;
18434 if (end == cur)
18435 break;
18436 count++;
18437 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018438 cur = end;
18439 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18440 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018441 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018442 VERROR_INT("xmlSchemaAssembleByXSI",
18443 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018444 return (-1);
18445 }
18446 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018447 return (ret);
18448}
18449
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018450#define VAL_CREATE_DICT if (vctxt->dict == NULL) vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018451
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018452static const xmlChar *
18453xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18454 const xmlChar *prefix)
18455{
18456 if (vctxt->sax != NULL) {
18457 int i, j;
18458 xmlSchemaNodeInfoPtr inode;
18459
18460 for (i = vctxt->depth; i >= 0; i--) {
18461 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18462 inode = vctxt->elemInfos[i];
18463 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18464 if (((prefix == NULL) &&
18465 (inode->nsBindings[j] == NULL)) ||
18466 ((prefix != NULL) && xmlStrEqual(prefix,
18467 inode->nsBindings[j]))) {
18468
18469 /*
18470 * Note that the namespace bindings are already
18471 * in a string dict.
18472 */
18473 return (inode->nsBindings[j+1]);
18474 }
18475 }
18476 }
18477 }
18478 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018479#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018480 } else if (vctxt->reader != NULL) {
18481 xmlChar *nsName;
18482
18483 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18484 if (nsName != NULL) {
18485 const xmlChar *ret;
18486
18487 VAL_CREATE_DICT;
18488 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18489 xmlFree(nsName);
18490 return (ret);
18491 } else
18492 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018493#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018494 } else {
18495 xmlNsPtr ns;
18496
18497 if ((vctxt->inode->node == NULL) ||
18498 (vctxt->inode->node->doc == NULL)) {
18499 VERROR_INT("xmlSchemaLookupNamespace",
18500 "no node or node's doc avaliable");
18501 return (NULL);
18502 }
18503 ns = xmlSearchNs(vctxt->inode->node->doc,
18504 vctxt->inode->node, prefix);
18505 if (ns != NULL)
18506 return (ns->href);
18507 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018508 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018509}
18510
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018511/*
18512* This one works on the schema of the validation context.
18513*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018514static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018515xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18516 xmlSchemaPtr schema,
18517 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018518 const xmlChar *value,
18519 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018520 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018521{
18522 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018523
18524 if (vctxt && (vctxt->schema == NULL)) {
18525 VERROR_INT("xmlSchemaValidateNotation",
18526 "a schema is needed on the validation context");
18527 return (-1);
18528 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018529 ret = xmlValidateQName(value, 1);
18530 if (ret != 0)
18531 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018532 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018533 xmlChar *localName = NULL;
18534 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018535
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018536 localName = xmlSplitQName2(value, &prefix);
18537 if (prefix != NULL) {
18538 const xmlChar *nsName = NULL;
18539
18540 if (vctxt != NULL)
18541 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18542 else if (node != NULL) {
18543 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18544 if (ns != NULL)
18545 nsName = ns->href;
18546 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018547 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018548 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018549 return (1);
18550 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018551 if (nsName == NULL) {
18552 xmlFree(prefix);
18553 xmlFree(localName);
18554 return (1);
18555 }
18556 if (xmlHashLookup2(schema->notaDecl, localName,
18557 nsName) != NULL) {
18558 if (valNeeded && (val != NULL)) {
18559 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18560 BAD_CAST xmlStrdup(nsName));
18561 if (*val == NULL)
18562 ret = -1;
18563 }
18564 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018565 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018566 xmlFree(prefix);
18567 xmlFree(localName);
18568 } else {
18569 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18570 if (valNeeded && (val != NULL)) {
18571 (*val) = xmlSchemaNewNOTATIONValue(
18572 BAD_CAST xmlStrdup(value), NULL);
18573 if (*val == NULL)
18574 ret = -1;
18575 }
18576 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018577 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018578 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018579 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018580 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018581}
18582
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018583/************************************************************************
18584 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018585 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018586 * *
18587 ************************************************************************/
18588
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018589/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018590 * xmlSchemaAugmentIDC:
18591 * @idcDef: the IDC definition
18592 *
18593 * Creates an augmented IDC definition item.
18594 *
18595 * Returns the item, or NULL on internal errors.
18596 */
18597static void
18598xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
18599 xmlSchemaValidCtxtPtr vctxt)
18600{
18601 xmlSchemaIDCAugPtr aidc;
18602
18603 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
18604 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018605 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018606 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
18607 NULL);
18608 return;
18609 }
18610 aidc->bubbleDepth = -1;
18611 aidc->def = idcDef;
18612 aidc->next = NULL;
18613 if (vctxt->aidcs == NULL)
18614 vctxt->aidcs = aidc;
18615 else {
18616 aidc->next = vctxt->aidcs;
18617 vctxt->aidcs = aidc;
18618 }
18619}
18620
18621/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018622 * xmlSchemaIDCNewBinding:
18623 * @idcDef: the IDC definition of this binding
18624 *
18625 * Creates a new IDC binding.
18626 *
18627 * Returns the new binding in case of succeeded, NULL on internal errors.
18628 */
18629static xmlSchemaPSVIIDCBindingPtr
18630xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
18631{
18632 xmlSchemaPSVIIDCBindingPtr ret;
18633
18634 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
18635 sizeof(xmlSchemaPSVIIDCBinding));
18636 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018637 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018638 "allocating a PSVI IDC binding item", NULL);
18639 return (NULL);
18640 }
18641 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
18642 ret->definition = idcDef;
18643 return (ret);
18644}
18645
18646/**
18647 * xmlSchemaIDCStoreNodeTableItem:
18648 * @vctxt: the WXS validation context
18649 * @item: the IDC node table item
18650 *
18651 * The validation context is used to store an IDC node table items.
18652 * They are stored to avoid copying them if IDC node-tables are merged
18653 * with corresponding parent IDC node-tables (bubbling).
18654 *
18655 * Returns 0 if succeeded, -1 on internal errors.
18656 */
18657static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018658xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018659 xmlSchemaPSVIIDCNodePtr item)
18660{
18661 /*
18662 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018663 */
18664 if (vctxt->idcNodes == NULL) {
18665 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018666 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
18667 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018668 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018669 "allocating the IDC node table item list", NULL);
18670 return (-1);
18671 }
18672 vctxt->sizeIdcNodes = 20;
18673 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
18674 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018675 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
18676 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018677 sizeof(xmlSchemaPSVIIDCNodePtr));
18678 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018679 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018680 "re-allocating the IDC node table item list", NULL);
18681 return (-1);
18682 }
18683 }
18684 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018685
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018686 return (0);
18687}
18688
18689/**
18690 * xmlSchemaIDCStoreKey:
18691 * @vctxt: the WXS validation context
18692 * @item: the IDC key
18693 *
18694 * The validation context is used to store an IDC key.
18695 *
18696 * Returns 0 if succeeded, -1 on internal errors.
18697 */
18698static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018699xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018700 xmlSchemaPSVIIDCKeyPtr key)
18701{
18702 /*
18703 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018704 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018705 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018706 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018707 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
18708 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018709 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018710 "allocating the IDC key storage list", NULL);
18711 return (-1);
18712 }
18713 vctxt->sizeIdcKeys = 40;
18714 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
18715 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018716 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
18717 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018718 sizeof(xmlSchemaPSVIIDCKeyPtr));
18719 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018720 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018721 "re-allocating the IDC key storage list", NULL);
18722 return (-1);
18723 }
18724 }
18725 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018726
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018727 return (0);
18728}
18729
18730/**
18731 * xmlSchemaIDCAppendNodeTableItem:
18732 * @bind: the IDC binding
18733 * @ntItem: the node-table item
18734 *
18735 * Appends the IDC node-table item to the binding.
18736 *
18737 * Returns 0 on success and -1 on internal errors.
18738 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018739static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018740xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
18741 xmlSchemaPSVIIDCNodePtr ntItem)
18742{
18743 if (bind->nodeTable == NULL) {
18744 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018745 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018746 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
18747 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018748 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018749 "allocating an array of IDC node-table items", NULL);
18750 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018751 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018752 } else if (bind->sizeNodes <= bind->nbNodes) {
18753 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018754 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
18755 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018756 sizeof(xmlSchemaPSVIIDCNodePtr));
18757 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018758 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018759 "re-allocating an array of IDC node-table items", NULL);
18760 return(-1);
18761 }
18762 }
18763 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018764 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018765}
18766
18767/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018768 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018769 * @vctxt: the WXS validation context
18770 * @matcher: the IDC matcher
18771 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018772 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018773 * of the given matcher. If none found, a new one is created
18774 * and added to the IDC table.
18775 *
18776 * Returns an IDC binding or NULL on internal errors.
18777 */
18778static xmlSchemaPSVIIDCBindingPtr
18779xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
18780 xmlSchemaIDCMatcherPtr matcher)
18781{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000018782 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018783
18784 info = vctxt->elemInfos[matcher->depth];
18785
18786 if (info->idcTable == NULL) {
18787 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
18788 if (info->idcTable == NULL)
18789 return (NULL);
18790 return(info->idcTable);
18791 } else {
18792 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018793
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018794 bind = info->idcTable;
18795 do {
18796 if (bind->definition == matcher->aidc->def)
18797 return(bind);
18798 if (bind->next == NULL) {
18799 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
18800 if (bind->next == NULL)
18801 return (NULL);
18802 return(bind->next);
18803 }
18804 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018805 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018806 }
18807 return (NULL);
18808}
18809
18810/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018811 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018812 * @key: the IDC key
18813 *
18814 * Frees an IDC key together with its compiled value.
18815 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018816static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018817xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
18818{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018819 if (key->val != NULL)
18820 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018821 xmlFree(key);
18822}
18823
18824/**
18825 * xmlSchemaIDCFreeBinding:
18826 *
18827 * Frees an IDC binding. Note that the node table-items
18828 * are not freed.
18829 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018830static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018831xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
18832{
18833 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018834 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
18835 int i;
18836 /*
18837 * Node-table items for keyrefs are not stored globally
18838 * to the validation context, since they are not bubbled.
18839 * We need to free them here.
18840 */
18841 for (i = 0; i < bind->nbNodes; i++) {
18842 xmlFree(bind->nodeTable[i]->keys);
18843 xmlFree(bind->nodeTable[i]);
18844 }
18845 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018846 xmlFree(bind->nodeTable);
18847 }
18848 xmlFree(bind);
18849}
18850
18851/**
18852 * xmlSchemaIDCFreeIDCTable:
18853 * @bind: the first IDC binding in the list
18854 *
18855 * Frees an IDC table, i.e. all the IDC bindings in the list.
18856 */
18857static void
18858xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
18859{
18860 xmlSchemaPSVIIDCBindingPtr prev;
18861
18862 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018863 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018864 bind = bind->next;
18865 xmlSchemaIDCFreeBinding(prev);
18866 }
18867}
18868
18869/**
18870 * xmlSchemaIDCFreeMatcherList:
18871 * @matcher: the first IDC matcher in the list
18872 *
18873 * Frees a list of IDC matchers.
18874 */
18875static void
18876xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
18877{
18878 xmlSchemaIDCMatcherPtr next;
18879
18880 while (matcher != NULL) {
18881 next = matcher->next;
18882 if (matcher->keySeqs != NULL) {
18883 int i;
18884 for (i = 0; i < matcher->sizeKeySeqs; i++)
18885 if (matcher->keySeqs[i] != NULL)
18886 xmlFree(matcher->keySeqs[i]);
18887 xmlFree(matcher->keySeqs);
18888 }
18889 xmlFree(matcher);
18890 matcher = next;
18891 }
18892}
18893
18894/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018895 * xmlSchemaIDCAddStateObject:
18896 * @vctxt: the WXS validation context
18897 * @matcher: the IDC matcher
18898 * @sel: the XPath information
18899 * @parent: the parent "selector" state object if any
18900 * @type: "selector" or "field"
18901 *
18902 * Creates/reuses and activates state objects for the given
18903 * XPath information; if the XPath expression consists of unions,
18904 * multiple state objects are created for every unioned expression.
18905 *
18906 * Returns 0 on success and -1 on internal errors.
18907 */
18908static int
18909xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
18910 xmlSchemaIDCMatcherPtr matcher,
18911 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018912 int type)
18913{
18914 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018915
18916 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018917 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018918 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018919 if (vctxt->xpathStatePool != NULL) {
18920 sto = vctxt->xpathStatePool;
18921 vctxt->xpathStatePool = sto->next;
18922 sto->next = NULL;
18923 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018924 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018925 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018926 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018927 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
18928 if (sto == NULL) {
18929 xmlSchemaVErrMemory(NULL,
18930 "allocating an IDC state object", NULL);
18931 return (-1);
18932 }
18933 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
18934 }
18935 /*
18936 * Add to global list.
18937 */
18938 if (vctxt->xpathStates != NULL)
18939 sto->next = vctxt->xpathStates;
18940 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018941
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018942 /*
18943 * Free the old xpath validation context.
18944 */
18945 if (sto->xpathCtxt != NULL)
18946 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
18947
18948 /*
18949 * Create a new XPath (pattern) validation context.
18950 */
18951 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
18952 (xmlPatternPtr) sel->xpathComp);
18953 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018954 VERROR_INT("xmlSchemaIDCAddStateObject",
18955 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000018956 return (-1);
18957 }
18958 sto->type = type;
18959 sto->depth = vctxt->depth;
18960 sto->matcher = matcher;
18961 sto->sel = sel;
18962 sto->nbHistory = 0;
18963
18964#if DEBUG_IDC
18965 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
18966 sto->sel->xpath);
18967#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018968 return (0);
18969}
18970
18971/**
18972 * xmlSchemaXPathEvaluate:
18973 * @vctxt: the WXS validation context
18974 * @nodeType: the nodeType of the current node
18975 *
18976 * Evaluates all active XPath state objects.
18977 *
18978 * Returns the number of IC "field" state objects which resolved to
18979 * this node, 0 if none resolved and -1 on internal errors.
18980 */
18981static int
18982xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018983 xmlElementType nodeType)
18984{
18985 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018986 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018987
18988 if (vctxt->xpathStates == NULL)
18989 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000018990
18991 if (nodeType == XML_ATTRIBUTE_NODE)
18992 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018993#if DEBUG_IDC
18994 {
18995 xmlChar *str = NULL;
18996 xmlGenericError(xmlGenericErrorContext,
18997 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018998 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
18999 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019000 FREE_AND_NULL(str)
19001 }
19002#endif
19003 /*
19004 * Process all active XPath state objects.
19005 */
19006 first = vctxt->xpathStates;
19007 sto = first;
19008 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019009#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019010 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019011 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
19012 sto->matcher->aidc->def->name, sto->sel->xpath);
19013 else
19014 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
19015 sto->matcher->aidc->def->name, sto->sel->xpath);
19016#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019017 if (nodeType == XML_ELEMENT_NODE)
19018 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019019 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019020 else
19021 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019022 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019023
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019024 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019025 VERROR_INT("xmlSchemaXPathEvaluate",
19026 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019027 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019028 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019029 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019030 goto next_sto;
19031 /*
19032 * Full match.
19033 */
19034#if DEBUG_IDC
19035 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019036 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019037#endif
19038 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019039 * Register a match in the state object history.
19040 */
19041 if (sto->history == NULL) {
19042 sto->history = (int *) xmlMalloc(5 * sizeof(int));
19043 if (sto->history == NULL) {
19044 xmlSchemaVErrMemory(NULL,
19045 "allocating the state object history", NULL);
19046 return(-1);
19047 }
19048 sto->sizeHistory = 10;
19049 } else if (sto->sizeHistory <= sto->nbHistory) {
19050 sto->sizeHistory *= 2;
19051 sto->history = (int *) xmlRealloc(sto->history,
19052 sto->sizeHistory * sizeof(int));
19053 if (sto->history == NULL) {
19054 xmlSchemaVErrMemory(NULL,
19055 "re-allocating the state object history", NULL);
19056 return(-1);
19057 }
19058 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019059 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019060
19061#ifdef DEBUG_IDC
19062 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19063 vctxt->depth);
19064#endif
19065
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019066 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19067 xmlSchemaIDCSelectPtr sel;
19068 /*
19069 * Activate state objects for the IDC fields of
19070 * the IDC selector.
19071 */
19072#if DEBUG_IDC
19073 xmlGenericError(xmlGenericErrorContext, "IDC: "
19074 "activating field states\n");
19075#endif
19076 sel = sto->matcher->aidc->def->fields;
19077 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019078 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19079 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19080 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019081 sel = sel->next;
19082 }
19083 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19084 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019085 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019086 */
19087#if DEBUG_IDC
19088 xmlGenericError(xmlGenericErrorContext,
19089 "IDC: key found\n");
19090#endif
19091 /*
19092 * Notify that the character value of this node is
19093 * needed.
19094 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019095 if (resolved == 0) {
19096 if ((vctxt->inode->flags &
19097 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19098 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19099 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019100 resolved++;
19101 }
19102next_sto:
19103 if (sto->next == NULL) {
19104 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019105 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019106 */
19107 head = first;
19108 sto = vctxt->xpathStates;
19109 } else
19110 sto = sto->next;
19111 }
19112 return (resolved);
19113}
19114
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019115static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019116xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019117 xmlChar **buf,
19118 xmlSchemaPSVIIDCKeyPtr *seq,
19119 int count)
19120{
19121 int i, res;
19122 const xmlChar *value = NULL;
19123
19124 *buf = xmlStrdup(BAD_CAST "[");
19125 for (i = 0; i < count; i++) {
19126 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019127 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19128 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019129 if (res == 0)
19130 *buf = xmlStrcat(*buf, value);
19131 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019132 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19133 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019134 *buf = xmlStrcat(*buf, BAD_CAST "???");
19135 }
19136 if (i < count -1)
19137 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19138 else
19139 *buf = xmlStrcat(*buf, BAD_CAST "'");
19140 if (value != NULL) {
19141 xmlFree((xmlChar *) value);
19142 value = NULL;
19143 }
19144 }
19145 *buf = xmlStrcat(*buf, BAD_CAST "]");
19146
19147 return (BAD_CAST *buf);
19148}
19149
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019150/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019151 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019152 * @vctxt: the WXS validation context
19153 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019154 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019155 *
19156 * Processes and pops the history items of the IDC state objects.
19157 * IDC key-sequences are validated/created on IDC bindings.
19158 *
19159 * Returns 0 on success and -1 on internal errors.
19160 */
19161static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019162xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019163 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019164{
19165 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019166 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019167 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019168 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019169
19170 if (vctxt->xpathStates == NULL)
19171 return (0);
19172 sto = vctxt->xpathStates;
19173
19174#if DEBUG_IDC
19175 {
19176 xmlChar *str = NULL;
19177 xmlGenericError(xmlGenericErrorContext,
19178 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019179 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19180 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019181 FREE_AND_NULL(str)
19182 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019183#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019184 /*
19185 * Evaluate the state objects.
19186 */
19187 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019188 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19189 if (res == -1) {
19190 VERROR_INT("xmlSchemaXPathProcessHistory",
19191 "calling xmlStreamPop()");
19192 return (-1);
19193 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019194#if DEBUG_IDC
19195 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19196 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019197#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019198 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019199 goto deregister_check;
19200
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019201 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019202
19203 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019204 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019205 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019206 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019207 sto = sto->next;
19208 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019209 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019210 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19211 if (! IS_SIMPLE_TYPE(type)) {
19212 /*
19213 * Not qualified if the field resolves to a node of non
19214 * simple type.
19215 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019216 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19217 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019218 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19219 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019220 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019221
19222 sto->nbHistory--;
19223 goto deregister_check;
19224 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019225 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019226 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019227 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019228 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019229 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019230 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019231 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19232 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019233 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019234 sto->nbHistory--;
19235 goto deregister_check;
19236 } else {
19237 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19238 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019239 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019240
19241 /*
19242 * The key will be anchored on the matcher's list of
19243 * key-sequences. The position in this list is determined
19244 * by the target node's depth relative to the matcher's
19245 * depth of creation (i.e. the depth of the scope element).
19246 */
19247 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019248 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019249
19250 /*
19251 * Create/grow the array of key-sequences.
19252 */
19253 if (matcher->keySeqs == NULL) {
19254 if (pos > 9)
19255 matcher->sizeKeySeqs = pos * 2;
19256 else
19257 matcher->sizeKeySeqs = 10;
19258 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19259 xmlMalloc(matcher->sizeKeySeqs *
19260 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19261 if (matcher->keySeqs == NULL) {
19262 xmlSchemaVErrMemory(NULL,
19263 "allocating an array of key-sequences",
19264 NULL);
19265 return(-1);
19266 }
19267 memset(matcher->keySeqs, 0,
19268 matcher->sizeKeySeqs *
19269 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19270 } else if (pos >= matcher->sizeKeySeqs) {
19271 int i = matcher->sizeKeySeqs;
19272
19273 matcher->sizeKeySeqs *= 2;
19274 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19275 xmlRealloc(matcher->keySeqs,
19276 matcher->sizeKeySeqs *
19277 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019278 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019279 xmlSchemaVErrMemory(NULL,
19280 "reallocating an array of key-sequences",
19281 NULL);
19282 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019283 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019284 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019285 * The array needs to be NULLed.
19286 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019287 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019288 for (; i < matcher->sizeKeySeqs; i++)
19289 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019290 }
19291
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019292 /*
19293 * Get/create the key-sequence.
19294 */
19295 keySeq = matcher->keySeqs[pos];
19296 if (keySeq == NULL) {
19297 goto create_sequence;
19298 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019299 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019300 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019301 * cvc-identity-constraint:
19302 * 3 For each node in the ·target node set· all
19303 * of the {fields}, with that node as the context
19304 * node, evaluate to either an empty node-set or
19305 * a node-set with exactly one member, which must
19306 * have a simple type.
19307 *
19308 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019309 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019310 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19311 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019312 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019313 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019314 "with more than one member",
19315 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019316 sto->nbHistory--;
19317 goto deregister_check;
19318 } else {
19319 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019320 }
19321 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019322
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019323create_sequence:
19324 /*
19325 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019326 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019327 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19328 matcher->aidc->def->nbFields *
19329 sizeof(xmlSchemaPSVIIDCKeyPtr));
19330 if (keySeq == NULL) {
19331 xmlSchemaVErrMemory(NULL,
19332 "allocating an IDC key-sequence", NULL);
19333 return(-1);
19334 }
19335 memset(keySeq, 0, matcher->aidc->def->nbFields *
19336 sizeof(xmlSchemaPSVIIDCKeyPtr));
19337 matcher->keySeqs[pos] = keySeq;
19338create_key:
19339 /*
19340 * Created a key once per node only.
19341 */
19342 if (key == NULL) {
19343 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19344 sizeof(xmlSchemaPSVIIDCKey));
19345 if (key == NULL) {
19346 xmlSchemaVErrMemory(NULL,
19347 "allocating a IDC key", NULL);
19348 xmlFree(keySeq);
19349 matcher->keySeqs[pos] = NULL;
19350 return(-1);
19351 }
19352 /*
19353 * Consume the compiled value.
19354 */
19355 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019356 key->val = vctxt->inode->val;
19357 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019358 /*
19359 * Store the key in a global list.
19360 */
19361 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19362 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019363 return (-1);
19364 }
19365 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019366 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019367 }
19368 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019369
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019370 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19371 xmlSchemaPSVIIDCBindingPtr bind;
19372 xmlSchemaPSVIIDCNodePtr ntItem;
19373 xmlSchemaIDCMatcherPtr matcher;
19374 xmlSchemaIDCPtr idc;
19375 int pos, i, j, nbKeys;
19376 /*
19377 * Here we have the following scenario:
19378 * An IDC 'selector' state object resolved to a target node,
19379 * during the time this target node was in the
19380 * ancestor-or-self axis, the 'field' state object(s) looked
19381 * out for matching nodes to create a key-sequence for this
19382 * target node. Now we are back to this target node and need
19383 * to put the key-sequence, together with the target node
19384 * itself, into the node-table of the corresponding IDC
19385 * binding.
19386 */
19387 matcher = sto->matcher;
19388 idc = matcher->aidc->def;
19389 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019390 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019391 /*
19392 * Check if the matcher has any key-sequences at all, plus
19393 * if it has a key-sequence for the current target node.
19394 */
19395 if ((matcher->keySeqs == NULL) ||
19396 (matcher->sizeKeySeqs <= pos)) {
19397 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19398 goto selector_key_error;
19399 else
19400 goto selector_leave;
19401 }
19402
19403 keySeq = &(matcher->keySeqs[pos]);
19404 if (*keySeq == NULL) {
19405 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19406 goto selector_key_error;
19407 else
19408 goto selector_leave;
19409 }
19410
19411 for (i = 0; i < nbKeys; i++) {
19412 if ((*keySeq)[i] == NULL) {
19413 /*
19414 * Not qualified, if not all fields did resolve.
19415 */
19416 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19417 /*
19418 * All fields of a "key" IDC must resolve.
19419 */
19420 goto selector_key_error;
19421 }
19422 goto selector_leave;
19423 }
19424 }
19425 /*
19426 * All fields did resolve.
19427 */
19428
19429 /*
19430 * 4.1 If the {identity-constraint category} is unique(/key),
19431 * then no two members of the ·qualified node set· have
19432 * ·key-sequences· whose members are pairwise equal, as
19433 * defined by Equal in [XML Schemas: Datatypes].
19434 *
19435 * Get the IDC binding from the matcher and check for
19436 * duplicate key-sequences.
19437 */
19438 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19439 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19440 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019441 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019442
19443 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019444 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019445 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019446 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019447 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019448 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019449 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019450 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019451 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019452 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019453 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019454 if (res == -1) {
19455 return (-1);
19456 } else if (res == 0)
19457 break;
19458 }
19459 if (res == 1) {
19460 /*
19461 * Duplicate found.
19462 */
19463 break;
19464 }
19465 i++;
19466 } while (i < bind->nbNodes);
19467 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019468 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019469 /*
19470 * TODO: Try to report the key-sequence.
19471 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019472 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19473 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019474 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019475 "Duplicate key-sequence %s",
19476 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19477 (*keySeq), nbKeys), NULL);
19478 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019479 goto selector_leave;
19480 }
19481 }
19482 /*
19483 * Add a node-table item to the IDC binding.
19484 */
19485 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19486 sizeof(xmlSchemaPSVIIDCNode));
19487 if (ntItem == NULL) {
19488 xmlSchemaVErrMemory(NULL,
19489 "allocating an IDC node-table item", NULL);
19490 xmlFree(*keySeq);
19491 *keySeq = NULL;
19492 return(-1);
19493 }
19494 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
19495
19496 /*
19497 * Store the node-table item on global list.
19498 */
19499 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19500 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19501 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019502 xmlFree(*keySeq);
19503 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019504 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019505 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019506 }
19507 /*
19508 * Init the node-table item. Consume the key-sequence.
19509 */
19510 ntItem->node = vctxt->node;
19511 ntItem->keys = *keySeq;
19512 *keySeq = NULL;
19513 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
19514 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19515 /*
19516 * Free the item, since keyref items won't be
19517 * put on a global list.
19518 */
19519 xmlFree(ntItem->keys);
19520 xmlFree(ntItem);
19521 }
19522 return (-1);
19523 }
19524
19525 goto selector_leave;
19526selector_key_error:
19527 /*
19528 * 4.2.1 (KEY) The ·target node set· and the
19529 * ·qualified node set· are equal, that is, every
19530 * member of the ·target node set· is also a member
19531 * of the ·qualified node set· and vice versa.
19532 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019533 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
19534 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019535selector_leave:
19536 /*
19537 * Free the key-sequence if not added to the IDC table.
19538 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019539 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019540 xmlFree(*keySeq);
19541 *keySeq = NULL;
19542 }
19543 } /* if selector */
19544
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019545 sto->nbHistory--;
19546
19547deregister_check:
19548 /*
19549 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019550 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019551 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019552#if DEBUG_IDC
19553 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
19554 sto->sel->xpath);
19555#endif
19556 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019557 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019558 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019559 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019560 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019561 nextsto = sto->next;
19562 /*
19563 * Unlink from the list of active XPath state objects.
19564 */
19565 vctxt->xpathStates = sto->next;
19566 sto->next = vctxt->xpathStatePool;
19567 /*
19568 * Link it to the pool of reusable state objects.
19569 */
19570 vctxt->xpathStatePool = sto;
19571 sto = nextsto;
19572 } else
19573 sto = sto->next;
19574 } /* while (sto != NULL) */
19575 return (0);
19576}
19577
19578/**
19579 * xmlSchemaIDCRegisterMatchers:
19580 * @vctxt: the WXS validation context
19581 * @elemDecl: the element declaration
19582 *
19583 * Creates helper objects to evaluate IDC selectors/fields
19584 * successively.
19585 *
19586 * Returns 0 if OK and -1 on internal errors.
19587 */
19588static int
19589xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
19590 xmlSchemaElementPtr elemDecl)
19591{
19592 xmlSchemaIDCMatcherPtr matcher, last = NULL;
19593 xmlSchemaIDCPtr idc, refIdc;
19594 xmlSchemaIDCAugPtr aidc;
19595
19596 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
19597 if (idc == NULL)
19598 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019599
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019600#if DEBUG_IDC
19601 {
19602 xmlChar *str = NULL;
19603 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019604 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019605 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19606 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019607 FREE_AND_NULL(str)
19608 }
19609#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019610 if (vctxt->inode->idcMatchers != NULL) {
19611 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19612 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019613 return (-1);
19614 }
19615 do {
19616 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19617 /*
19618 * Since IDCs bubbles are expensive we need to know the
19619 * depth at which the bubbles should stop; this will be
19620 * the depth of the top-most keyref IDC. If no keyref
19621 * references a key/unique IDC, the bubbleDepth will
19622 * be -1, indicating that no bubbles are needed.
19623 */
19624 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
19625 if (refIdc != NULL) {
19626 /*
19627 * Lookup the augmented IDC.
19628 */
19629 aidc = vctxt->aidcs;
19630 while (aidc != NULL) {
19631 if (aidc->def == refIdc)
19632 break;
19633 aidc = aidc->next;
19634 }
19635 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019636 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019637 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019638 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019639 return (-1);
19640 }
19641 if ((aidc->bubbleDepth == -1) ||
19642 (vctxt->depth < aidc->bubbleDepth))
19643 aidc->bubbleDepth = vctxt->depth;
19644 }
19645 }
19646 /*
19647 * Lookup the augmented IDC item for the IDC definition.
19648 */
19649 aidc = vctxt->aidcs;
19650 while (aidc != NULL) {
19651 if (aidc->def == idc)
19652 break;
19653 aidc = aidc->next;
19654 }
19655 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019656 VERROR_INT("xmlSchemaIDCRegisterMatchers",
19657 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019658 return (-1);
19659 }
19660 /*
19661 * Create an IDC matcher for every IDC definition.
19662 */
19663 matcher = (xmlSchemaIDCMatcherPtr)
19664 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
19665 if (matcher == NULL) {
19666 xmlSchemaVErrMemory(vctxt,
19667 "allocating an IDC matcher", NULL);
19668 return (-1);
19669 }
19670 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
19671 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019672 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019673 else
19674 last->next = matcher;
19675 last = matcher;
19676
19677 matcher->type = IDC_MATCHER;
19678 matcher->depth = vctxt->depth;
19679 matcher->aidc = aidc;
19680#if DEBUG_IDC
19681 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
19682#endif
19683 /*
19684 * Init the automaton state object.
19685 */
19686 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019687 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019688 return (-1);
19689
19690 idc = idc->next;
19691 } while (idc != NULL);
19692 return (0);
19693}
19694
19695/**
19696 * xmlSchemaBubbleIDCNodeTables:
19697 * @depth: the current tree depth
19698 *
19699 * Merges IDC bindings of an element at @depth into the corresponding IDC
19700 * bindings of its parent element. If a duplicate note-table entry is found,
19701 * both, the parent node-table entry and child entry are discarded from the
19702 * node-table of the parent.
19703 *
19704 * Returns 0 if OK and -1 on internal errors.
19705 */
19706static int
19707xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
19708{
19709 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019710 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
19711 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019712 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
19713 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019714 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019715 int duplTop;
19716
19717 /*
19718 * The node table has the following sections:
19719 *
19720 * O --> old node-table entries (first)
19721 * O
19722 * + --> new node-table entries
19723 * +
19724 * % --> new duplicate node-table entries
19725 * %
19726 * # --> old duplicate node-table entries
19727 * # (last)
19728 *
19729 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019730 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019731 if (bind == NULL) {
19732 /* Fine, no table, no bubbles. */
19733 return (0);
19734 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019735
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019736 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
19737 /*
19738 * Walk all bindings; create new or add to existing bindings.
19739 * Remove duplicate key-sequences.
19740 */
19741start_binding:
19742 while (bind != NULL) {
19743 /*
19744 * Skip keyref IDCs.
19745 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019746 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19747 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019748 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019749 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019750 /*
19751 * Check if the key/unique IDC table needs to be bubbled.
19752 */
19753 aidc = vctxt->aidcs;
19754 do {
19755 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019756 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019757 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019758 bind = bind->next;
19759 goto start_binding;
19760 }
19761 break;
19762 }
19763 aidc = aidc->next;
19764 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019765
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019766 if (parTable != NULL)
19767 parBind = *parTable;
19768 while (parBind != NULL) {
19769 /*
19770 * Search a matching parent binding for the
19771 * IDC definition.
19772 */
19773 if (parBind->definition == bind->definition) {
19774
19775 /*
19776 * Compare every node-table entry of the child node,
19777 * i.e. the key-sequence within, ...
19778 */
19779 oldNum = parBind->nbNodes; /* Skip newly added items. */
19780 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019781 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019782
19783 for (i = 0; i < bind->nbNodes; i++) {
19784 node = bind->nodeTable[i];
19785 if (node == NULL)
19786 continue;
19787 /*
19788 * ...with every key-sequence of the parent node, already
19789 * evaluated to be a duplicate key-sequence.
19790 */
19791 if (parBind->nbDupls != 0) {
19792 j = bind->nbNodes + newDupls;
19793 while (j < duplTop) {
19794 parNode = parBind->nodeTable[j];
19795 for (k = 0; k < bind->definition->nbFields; k++) {
19796 key = node->keys[k];
19797 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019798 ret = xmlSchemaAreValuesEqual(key->val,
19799 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019800 if (ret == -1) {
19801 /* TODO: Internal error */
19802 return(-1);
19803 } else if (ret == 0)
19804 break;
19805
19806 }
19807 if (ret == 1)
19808 /* Duplicate found. */
19809 break;
19810 j++;
19811 }
19812 if (j != duplTop) {
19813 /* Duplicate found. */
19814 continue;
19815 }
19816 }
19817 /*
19818 * ... and with every key-sequence of the parent node.
19819 */
19820 j = 0;
19821 while (j < oldNum) {
19822 parNode = parBind->nodeTable[j];
19823 /*
19824 * Compare key by key.
19825 */
19826 for (k = 0; k < parBind->definition->nbFields; k++) {
19827 key = node->keys[k];
19828 parKey = parNode->keys[k];
19829
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019830 ret = xmlSchemaAreValuesEqual(key->val,
19831 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019832 if (ret == -1) {
19833 /* TODO: Internal error */
19834 } else if (ret == 0)
19835 break;
19836
19837 }
19838 if (ret == 1)
19839 /*
19840 * The key-sequences are equal.
19841 */
19842 break;
19843 j++;
19844 }
19845 if (j != oldNum) {
19846 /*
19847 * Handle duplicates.
19848 */
19849 newDupls++;
19850 oldNum--;
19851 parBind->nbNodes--;
19852 /*
19853 * Move last old item to pos of duplicate.
19854 */
19855 parBind->nodeTable[j] =
19856 parBind->nodeTable[oldNum];
19857
19858 if (parBind->nbNodes != oldNum) {
19859 /*
19860 * If new items exist, move last new item to
19861 * last of old items.
19862 */
19863 parBind->nodeTable[oldNum] =
19864 parBind->nodeTable[parBind->nbNodes];
19865 }
19866 /*
19867 * Move duplicate to last pos of new/old items.
19868 */
19869 parBind->nodeTable[parBind->nbNodes] = parNode;
19870
19871 } else {
19872 /*
19873 * Add the node-table entry (node and key-sequence) of
19874 * the child node to the node table of the parent node.
19875 */
19876 if (parBind->nodeTable == NULL) {
19877 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019878 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019879 if (parBind->nodeTable == NULL) {
19880 xmlSchemaVErrMemory(NULL,
19881 "allocating IDC list of node-table items", NULL);
19882 return(-1);
19883 }
19884 parBind->sizeNodes = 1;
19885 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019886 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019887 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19888 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
19889 sizeof(xmlSchemaPSVIIDCNodePtr));
19890 if (parBind->nodeTable == NULL) {
19891 xmlSchemaVErrMemory(NULL,
19892 "re-allocating IDC list of node-table items", NULL);
19893 return(-1);
19894 }
19895 }
19896
19897 /*
19898 * Move first old duplicate to last position
19899 * of old duplicates +1.
19900 */
19901 if (parBind->nbDupls != 0) {
19902 parBind->nodeTable[duplTop] =
19903 parBind->nodeTable[parBind->nbNodes + newDupls];
19904 }
19905 /*
19906 * Move first new duplicate to last position of
19907 * new duplicates +1.
19908 */
19909 if (newDupls != 0) {
19910 parBind->nodeTable[parBind->nbNodes + newDupls] =
19911 parBind->nodeTable[parBind->nbNodes];
19912 }
19913 /*
19914 * Append the new node-table entry to the 'new node-table
19915 * entries' section.
19916 */
19917 parBind->nodeTable[parBind->nbNodes] = node;
19918 parBind->nbNodes++;
19919 duplTop++;
19920 }
19921 }
19922 parBind->nbDupls += newDupls;
19923 break;
19924 }
19925 if (parBind->next == NULL)
19926 lastParBind = parBind;
19927 parBind = parBind->next;
19928 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000019929 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019930 /*
19931 * No binding for the IDC was found: create a new one and
19932 * copy all node-tables.
19933 */
19934 parBind = xmlSchemaIDCNewBinding(bind->definition);
19935 if (parBind == NULL)
19936 return(-1);
19937
19938 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19939 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
19940 if (parBind->nodeTable == NULL) {
19941 xmlSchemaVErrMemory(NULL,
19942 "allocating an array of IDC node-table items", NULL);
19943 xmlSchemaIDCFreeBinding(parBind);
19944 return(-1);
19945 }
19946 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019947 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019948 memcpy(parBind->nodeTable, bind->nodeTable,
19949 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019950 if (*parTable == NULL)
19951 *parTable = parBind;
19952 else
19953 lastParBind->next = parBind;
19954 }
19955 bind = bind->next;
19956 }
19957 return (0);
19958}
19959
19960/**
19961 * xmlSchemaCheckCVCIDCKeyRef:
19962 * @vctxt: the WXS validation context
19963 * @elemDecl: the element declaration
19964 *
19965 * Check the cvc-idc-keyref constraints.
19966 */
19967static int
19968xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
19969{
19970 xmlSchemaPSVIIDCBindingPtr refbind, bind;
19971
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019972 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019973 /*
19974 * Find a keyref.
19975 */
19976 while (refbind != NULL) {
19977 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19978 int i, j, k, res;
19979 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
19980 xmlSchemaPSVIIDCKeyPtr refKey, key;
19981
19982 /*
19983 * Find the referred key/unique.
19984 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019985 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019986 do {
19987 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
19988 bind->definition)
19989 break;
19990 bind = bind->next;
19991 } while (bind != NULL);
19992
19993 /*
19994 * Search for a matching key-sequences.
19995 */
19996 for (i = 0; i < refbind->nbNodes; i++) {
19997 res = 0;
19998 if (bind != NULL) {
19999 refKeys = refbind->nodeTable[i]->keys;
20000 for (j = 0; j < bind->nbNodes; j++) {
20001 keys = bind->nodeTable[j]->keys;
20002 for (k = 0; k < bind->definition->nbFields; k++) {
20003 refKey = refKeys[k];
20004 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020005 res = xmlSchemaAreValuesEqual(key->val,
20006 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020007 if (res == 0)
20008 break;
20009 else if (res == -1) {
20010 return (-1);
20011 }
20012 }
20013 if (res == 1) {
20014 /*
20015 * Match found.
20016 */
20017 break;
20018 }
20019 }
20020 }
20021 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020022 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020023 /* TODO: Report the key-sequence. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020024 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20025 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020026 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020027 "No match found for key-sequence %s of key "
20028 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020029 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020030 refbind->nodeTable[i]->keys,
20031 refbind->definition->nbFields),
20032 xmlSchemaFormatQName(&strB,
20033 refbind->definition->targetNamespace,
20034 refbind->definition->name));
20035 FREE_AND_NULL(str);
20036 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020037 }
20038 }
20039 }
20040 refbind = refbind->next;
20041 }
20042 return (0);
20043}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020044
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020045/************************************************************************
20046 * *
20047 * XML Reader validation code *
20048 * *
20049 ************************************************************************/
20050
20051static xmlSchemaAttrInfoPtr
20052xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020053{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020054 xmlSchemaAttrInfoPtr iattr;
20055 /*
20056 * Grow/create list of attribute infos.
20057 */
20058 if (vctxt->attrInfos == NULL) {
20059 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20060 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
20061 vctxt->sizeAttrInfos = 1;
20062 if (vctxt->attrInfos == NULL) {
20063 xmlSchemaVErrMemory(vctxt,
20064 "allocating attribute info list", NULL);
20065 return (NULL);
20066 }
20067 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
20068 vctxt->sizeAttrInfos++;
20069 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20070 xmlRealloc(vctxt->attrInfos,
20071 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
20072 if (vctxt->attrInfos == NULL) {
20073 xmlSchemaVErrMemory(vctxt,
20074 "re-allocating attribute info list", NULL);
20075 return (NULL);
20076 }
20077 } else {
20078 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
20079 if (iattr->localName != NULL) {
20080 VERROR_INT("xmlSchemaGetFreshAttrInfo",
20081 "attr info not cleared");
20082 return (NULL);
20083 }
20084 iattr->nodeType = XML_ATTRIBUTE_NODE;
20085 return (iattr);
20086 }
20087 /*
20088 * Create an attribute info.
20089 */
20090 iattr = (xmlSchemaAttrInfoPtr)
20091 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20092 if (iattr == NULL) {
20093 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20094 return (NULL);
20095 }
20096 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20097 iattr->nodeType = XML_ATTRIBUTE_NODE;
20098 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20099
20100 return (iattr);
20101}
20102
20103static int
20104xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20105 xmlNodePtr attrNode,
20106 const xmlChar *localName,
20107 const xmlChar *nsName,
20108 int ownedNames,
20109 xmlChar *value,
20110 int ownedValue)
20111{
20112 xmlSchemaAttrInfoPtr attr;
20113
20114 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20115 if (attr == NULL) {
20116 VERROR_INT("xmlSchemaPushAttribute",
20117 "calling xmlSchemaGetFreshAttrInfo()");
20118 return (-1);
20119 }
20120 attr->node = attrNode;
20121 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20122 attr->localName = localName;
20123 attr->nsName = nsName;
20124 if (ownedNames)
20125 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20126 /*
20127 * Evaluate if it's an XSI attribute.
20128 */
20129 if (nsName != NULL) {
20130 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20131 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20132 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20133 }
20134 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20135 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20136 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20137 }
20138 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20139 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20140 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20141 }
20142 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20143 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20144 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20145 }
20146 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20147 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20148 }
20149 }
20150 attr->value = value;
20151 if (ownedValue)
20152 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20153 if (attr->metaType != 0)
20154 attr->state = XML_SCHEMAS_ATTR_META;
20155 return (0);
20156}
20157
20158static void
20159xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20160{
20161 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20162 FREE_AND_NULL(ielem->localName);
20163 FREE_AND_NULL(ielem->nsName);
20164 } else {
20165 ielem->localName = NULL;
20166 ielem->nsName = NULL;
20167 }
20168 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20169 FREE_AND_NULL(ielem->value);
20170 } else {
20171 ielem->value = NULL;
20172 }
20173 if (ielem->val != NULL) {
20174 xmlSchemaFreeValue(ielem->val);
20175 ielem->val = NULL;
20176 }
20177 if (ielem->idcMatchers != NULL) {
20178 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20179 ielem->idcMatchers = NULL;
20180 }
20181 if (ielem->idcTable != NULL) {
20182 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20183 ielem->idcTable = NULL;
20184 }
20185 if (ielem->regexCtxt != NULL) {
20186 xmlRegFreeExecCtxt(ielem->regexCtxt);
20187 ielem->regexCtxt = NULL;
20188 }
20189 if (ielem->nsBindings != NULL) {
20190 xmlFree((xmlChar **)ielem->nsBindings);
20191 ielem->nsBindings = NULL;
20192 ielem->nbNsBindings = 0;
20193 ielem->sizeNsBindings = 0;
20194 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020195}
20196
20197/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020198 * xmlSchemaGetFreshElemInfo:
20199 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020200 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020201 * Creates/reuses and initializes the element info item for
20202 * the currect tree depth.
20203 *
20204 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020205 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020206static xmlSchemaNodeInfoPtr
20207xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020208{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020209 xmlSchemaNodeInfoPtr info = NULL;
20210
20211 if (vctxt->depth > vctxt->sizeElemInfos) {
20212 VERROR_INT("xmlSchemaGetFreshElemInfo",
20213 "inconsistent depth encountered");
20214 return (NULL);
20215 }
20216 if (vctxt->elemInfos == NULL) {
20217 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20218 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20219 if (vctxt->elemInfos == NULL) {
20220 xmlSchemaVErrMemory(vctxt,
20221 "allocating the element info array", NULL);
20222 return (NULL);
20223 }
20224 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20225 vctxt->sizeElemInfos = 10;
20226 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20227 int i = vctxt->sizeElemInfos;
20228
20229 vctxt->sizeElemInfos *= 2;
20230 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20231 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20232 sizeof(xmlSchemaNodeInfoPtr));
20233 if (vctxt->elemInfos == NULL) {
20234 xmlSchemaVErrMemory(vctxt,
20235 "re-allocating the element info array", NULL);
20236 return (NULL);
20237 }
20238 /*
20239 * We need the new memory to be NULLed.
20240 * TODO: Use memset instead?
20241 */
20242 for (; i < vctxt->sizeElemInfos; i++)
20243 vctxt->elemInfos[i] = NULL;
20244 } else
20245 info = vctxt->elemInfos[vctxt->depth];
20246
20247 if (info == NULL) {
20248 info = (xmlSchemaNodeInfoPtr)
20249 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20250 if (info == NULL) {
20251 xmlSchemaVErrMemory(vctxt,
20252 "allocating an element info", NULL);
20253 return (NULL);
20254 }
20255 vctxt->elemInfos[vctxt->depth] = info;
20256 } else {
20257 if (info->localName != NULL) {
20258 VERROR_INT("xmlSchemaGetFreshElemInfo",
20259 "elem info has not been cleared");
20260 return (NULL);
20261 }
20262 }
20263 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20264 info->nodeType = XML_ELEMENT_NODE;
20265 info->depth = vctxt->depth;
20266
20267 return (info);
20268}
20269
20270#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20271#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20272#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20273
20274static int
20275xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20276 xmlNodePtr node,
20277 xmlSchemaTypePtr type,
20278 xmlSchemaValType valType,
20279 const xmlChar * value,
20280 xmlSchemaValPtr val,
20281 unsigned long length,
20282 int fireErrors)
20283{
20284 int ret, error = 0;
20285
20286 xmlSchemaTypePtr tmpType;
20287 xmlSchemaFacetLinkPtr facetLink;
20288 xmlSchemaFacetPtr facet;
20289 unsigned long len = 0;
20290 xmlSchemaWhitespaceValueType ws;
20291
20292 /*
20293 * In Libxml2, derived built-in types have currently no explicit facets.
20294 */
20295 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020296 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020297
20298 /*
20299 * NOTE: Do not jump away, if the facetSet of the given type is
20300 * empty: until now, "pattern" and "enumeration" facets of the
20301 * *base types* need to be checked as well.
20302 */
20303 if (type->facetSet == NULL)
20304 goto pattern_and_enum;
20305
20306 if (! VARIETY_ATOMIC(type)) {
20307 if (VARIETY_LIST(type))
20308 goto variety_list;
20309 else
20310 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020311 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020312 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020313 * Whitespace handling is only of importance for string-based
20314 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020315 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020316 tmpType = xmlSchemaGetPrimitiveType(type);
20317 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20318 IS_ANY_SIMPLE_TYPE(tmpType)) {
20319 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20320 } else
20321 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20322 /*
20323 * If the value was not computed (for string or
20324 * anySimpleType based types), then use the provided
20325 * type.
20326 */
20327 if (val == NULL)
20328 valType = valType;
20329 else
20330 valType = xmlSchemaGetValType(val);
20331
20332 ret = 0;
20333 for (facetLink = type->facetSet; facetLink != NULL;
20334 facetLink = facetLink->next) {
20335 /*
20336 * Skip the pattern "whiteSpace": it is used to
20337 * format the character content beforehand.
20338 */
20339 switch (facetLink->facet->type) {
20340 case XML_SCHEMA_FACET_WHITESPACE:
20341 case XML_SCHEMA_FACET_PATTERN:
20342 case XML_SCHEMA_FACET_ENUMERATION:
20343 continue;
20344 case XML_SCHEMA_FACET_LENGTH:
20345 case XML_SCHEMA_FACET_MINLENGTH:
20346 case XML_SCHEMA_FACET_MAXLENGTH:
20347 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20348 valType, value, val, &len, ws);
20349 break;
20350 default:
20351 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20352 valType, value, val, ws);
20353 break;
20354 }
20355 if (ret < 0) {
20356 AERROR_INT("xmlSchemaValidateFacets",
20357 "validating against a atomic type facet");
20358 return (-1);
20359 } else if (ret > 0) {
20360 if (fireErrors)
20361 xmlSchemaFacetErr(actxt, ret, node,
20362 value, len, type, facetLink->facet, NULL, NULL, NULL);
20363 else
20364 return (ret);
20365 if (error == 0)
20366 error = ret;
20367 }
20368 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020369 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020370
20371variety_list:
20372 if (! VARIETY_LIST(type))
20373 goto pattern_and_enum;
20374 /*
20375 * "length", "minLength" and "maxLength" of list types.
20376 */
20377 ret = 0;
20378 for (facetLink = type->facetSet; facetLink != NULL;
20379 facetLink = facetLink->next) {
20380
20381 switch (facetLink->facet->type) {
20382 case XML_SCHEMA_FACET_LENGTH:
20383 case XML_SCHEMA_FACET_MINLENGTH:
20384 case XML_SCHEMA_FACET_MAXLENGTH:
20385 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20386 value, length, NULL);
20387 break;
20388 default:
20389 continue;
20390 }
20391 if (ret < 0) {
20392 AERROR_INT("xmlSchemaValidateFacets",
20393 "validating against a list type facet");
20394 return (-1);
20395 } else if (ret > 0) {
20396 if (fireErrors)
20397 xmlSchemaFacetErr(actxt, ret, node,
20398 value, length, type, facetLink->facet, NULL, NULL, NULL);
20399 else
20400 return (ret);
20401 if (error == 0)
20402 error = ret;
20403 }
20404 ret = 0;
20405 }
20406
20407pattern_and_enum:
20408 if (error >= 0) {
20409 int found = 0;
20410 /*
20411 * Process enumerations. Facet values are in the value space
20412 * of the defining type's base type. This seems to be a bug in the
20413 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20414 * Only the first set of enumerations in the ancestor-or-self axis
20415 * is used for validation.
20416 */
20417 ret = 0;
20418 tmpType = type;
20419 do {
20420 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20421 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20422 continue;
20423 found = 1;
20424 ret = xmlSchemaAreValuesEqual(facet->val, val);
20425 if (ret == 1)
20426 break;
20427 else if (ret < 0) {
20428 AERROR_INT("xmlSchemaValidateFacets",
20429 "validating against an enumeration facet");
20430 return (-1);
20431 }
20432 }
20433 if (ret != 0)
20434 break;
20435 tmpType = tmpType->baseType;
20436 } while ((tmpType != NULL) &&
20437 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20438 if (found && (ret == 0)) {
20439 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20440 if (fireErrors) {
20441 xmlSchemaFacetErr(actxt, ret, node,
20442 value, 0, type, NULL, NULL, NULL, NULL);
20443 } else
20444 return (ret);
20445 if (error == 0)
20446 error = ret;
20447 }
20448 }
20449
20450 if (error >= 0) {
20451 int found;
20452 /*
20453 * Process patters. Pattern facets are ORed at type level
20454 * and ANDed if derived. Walk the base type axis.
20455 */
20456 tmpType = type;
20457 facet = NULL;
20458 do {
20459 found = 0;
20460 for (facetLink = tmpType->facetSet; facetLink != NULL;
20461 facetLink = facetLink->next) {
20462 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20463 continue;
20464 found = 1;
20465 /*
20466 * NOTE that for patterns, @value needs to be the
20467 * normalized vaule.
20468 */
20469 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20470 if (ret == 1)
20471 break;
20472 else if (ret < 0) {
20473 AERROR_INT("xmlSchemaValidateFacets",
20474 "validating against a pattern facet");
20475 return (-1);
20476 } else {
20477 /*
20478 * Save the last non-validating facet.
20479 */
20480 facet = facetLink->facet;
20481 }
20482 }
20483 if (found && (ret != 1)) {
20484 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20485 if (fireErrors) {
20486 xmlSchemaFacetErr(actxt, ret, node,
20487 value, 0, type, facet, NULL, NULL, NULL);
20488 } else
20489 return (ret);
20490 if (error == 0)
20491 error = ret;
20492 break;
20493 }
20494 tmpType = tmpType->baseType;
20495 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20496 }
20497
20498 return (error);
20499}
20500
20501static xmlChar *
20502xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20503 const xmlChar *value)
20504{
20505 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20506 case XML_SCHEMA_WHITESPACE_COLLAPSE:
20507 return (xmlSchemaCollapseString(value));
20508 case XML_SCHEMA_WHITESPACE_REPLACE:
20509 return (xmlSchemaWhiteSpaceReplace(value));
20510 default:
20511 return (NULL);
20512 }
20513}
20514
20515static int
20516xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
20517 const xmlChar *value,
20518 xmlSchemaValPtr *val,
20519 int valNeeded)
20520{
20521 int ret;
20522 const xmlChar *nsName;
20523 xmlChar *local, *prefix = NULL;
20524
20525 ret = xmlValidateQName(value, 1);
20526 if (ret != 0) {
20527 if (ret == -1) {
20528 VERROR_INT("xmlSchemaValidateQName",
20529 "calling xmlValidateQName()");
20530 return (-1);
20531 }
20532 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
20533 }
20534 /*
20535 * NOTE: xmlSplitQName2 will always return a duplicated
20536 * strings.
20537 */
20538 local = xmlSplitQName2(value, &prefix);
20539 if (local == NULL)
20540 local = xmlStrdup(value);
20541 /*
20542 * OPTIMIZE TODO: Use flags for:
20543 * - is there any namespace binding?
20544 * - is there a default namespace?
20545 */
20546 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20547
20548 if (prefix != NULL) {
20549 xmlFree(prefix);
20550 /*
20551 * A namespace must be found if the prefix is
20552 * NOT NULL.
20553 */
20554 if (nsName == NULL) {
20555 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20556 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
20557 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20558 "The QName value '%s' has no "
20559 "corresponding namespace declaration in "
20560 "scope", value, NULL);
20561 if (local != NULL)
20562 xmlFree(local);
20563 return (ret);
20564 }
20565 }
20566 if (valNeeded && val) {
20567 if (nsName != NULL)
20568 *val = xmlSchemaNewQNameValue(
20569 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
20570 else
20571 *val = xmlSchemaNewQNameValue(NULL,
20572 BAD_CAST local);
20573 } else
20574 xmlFree(local);
20575 return (0);
20576}
20577
20578/*
20579* cvc-simple-type
20580*/
20581static int
20582xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
20583 xmlNodePtr node,
20584 xmlSchemaTypePtr type,
20585 const xmlChar *value,
20586 xmlSchemaValPtr *retVal,
20587 int fireErrors,
20588 int normalize,
20589 int isNormalized)
20590{
20591 int ret = 0, valNeeded = (retVal) ? 1 : 0;
20592 xmlSchemaValPtr val = NULL;
20593 xmlSchemaWhitespaceValueType ws;
20594 xmlChar *normValue = NULL;
20595
20596#define NORMALIZE(atype) \
20597 if ((! isNormalized) && \
20598 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
20599 normValue = xmlSchemaNormalizeValue(atype, value); \
20600 if (normValue != NULL) \
20601 value = normValue; \
20602 isNormalized = 1; \
20603 }
20604
20605 if ((retVal != NULL) && (*retVal != NULL)) {
20606 xmlSchemaFreeValue(*retVal);
20607 *retVal = NULL;
20608 }
20609 /*
20610 * 3.14.4 Simple Type Definition Validation Rules
20611 * Validation Rule: String Valid
20612 */
20613 /*
20614 * 1 It is schema-valid with respect to that definition as defined
20615 * by Datatype Valid in [XML Schemas: Datatypes].
20616 */
20617 /*
20618 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
20619 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
20620 * the string must be a ·declared entity name·.
20621 */
20622 /*
20623 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
20624 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
20625 * then every whitespace-delimited substring of the string must be a ·declared
20626 * entity name·.
20627 */
20628 /*
20629 * 2.3 otherwise no further condition applies.
20630 */
20631 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
20632 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020633 if (value == NULL)
20634 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020635 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
20636 xmlSchemaTypePtr biType; /* The built-in type. */
20637 /*
20638 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
20639 * a literal in the ·lexical space· of {base type definition}"
20640 */
20641 /*
20642 * Whitespace-normalize.
20643 */
20644 NORMALIZE(type);
20645 if (type->type != XML_SCHEMA_TYPE_BASIC) {
20646 /*
20647 * Get the built-in type.
20648 */
20649 biType = type->baseType;
20650 while ((biType != NULL) &&
20651 (biType->type != XML_SCHEMA_TYPE_BASIC))
20652 biType = biType->baseType;
20653
20654 if (biType == NULL) {
20655 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20656 "could not get the built-in type");
20657 goto internal_error;
20658 }
20659 } else
20660 biType = type;
20661 /*
20662 * NOTATIONs need to be processed here, since they need
20663 * to lookup in the hashtable of NOTATION declarations of the schema.
20664 */
20665 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
20666 switch (biType->builtInType) {
20667 case XML_SCHEMAS_NOTATION:
20668 ret = xmlSchemaValidateNotation(
20669 (xmlSchemaValidCtxtPtr) actxt,
20670 ((xmlSchemaValidCtxtPtr) actxt)->schema,
20671 NULL, value, &val, valNeeded);
20672 break;
20673 case XML_SCHEMAS_QNAME:
20674 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
20675 value, &val, valNeeded);
20676 break;
20677 default:
20678 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20679 if (valNeeded)
20680 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20681 value, &val, NULL);
20682 else
20683 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20684 value, NULL, NULL);
20685 break;
20686 }
20687 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
20688 switch (biType->builtInType) {
20689 case XML_SCHEMAS_NOTATION:
20690 ret = xmlSchemaValidateNotation(NULL,
20691 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
20692 value, &val, valNeeded);
20693 break;
20694 default:
20695 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20696 if (valNeeded)
20697 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20698 value, &val, node);
20699 else
20700 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
20701 value, NULL, node);
20702 break;
20703 }
20704 } else {
20705 /*
20706 * Validation via a public API is not implemented yet.
20707 */
20708 TODO
20709 goto internal_error;
20710 }
20711 if (ret != 0) {
20712 if (ret < 0) {
20713 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20714 "validating against a built-in type");
20715 goto internal_error;
20716 }
20717 if (VARIETY_LIST(type))
20718 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20719 else
20720 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20721 }
20722 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20723 /*
20724 * Check facets.
20725 */
20726 ret = xmlSchemaValidateFacets(actxt, node, type,
20727 (xmlSchemaValType) biType->builtInType, value, val,
20728 0, fireErrors);
20729 if (ret != 0) {
20730 if (ret < 0) {
20731 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20732 "validating facets of atomic simple type");
20733 goto internal_error;
20734 }
20735 if (VARIETY_LIST(type))
20736 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20737 else
20738 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
20739 }
20740 }
20741 if (fireErrors && (ret > 0))
20742 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20743 } else if (VARIETY_LIST(type)) {
20744
20745 xmlSchemaTypePtr itemType;
20746 const xmlChar *cur, *end;
20747 xmlChar *tmpValue = NULL;
20748 unsigned long len = 0;
20749 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
20750 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
20751 * of white space separated tokens, each of which ·match·es a literal
20752 * in the ·lexical space· of {item type definition}
20753 */
20754 /*
20755 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
20756 * the list type has an enum or pattern facet.
20757 */
20758 NORMALIZE(type);
20759 /*
20760 * VAL TODO: Optimize validation of empty values.
20761 * VAL TODO: We do not have computed values for lists.
20762 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000020763 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020764 cur = value;
20765 do {
20766 while (IS_BLANK_CH(*cur))
20767 cur++;
20768 end = cur;
20769 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
20770 end++;
20771 if (end == cur)
20772 break;
20773 tmpValue = xmlStrndup(cur, end - cur);
20774 len++;
20775
20776 if (valNeeded)
20777 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20778 tmpValue, &curVal, fireErrors, 0, 1);
20779 else
20780 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
20781 tmpValue, NULL, fireErrors, 0, 1);
20782 FREE_AND_NULL(tmpValue);
20783 if (curVal != NULL) {
20784 /*
20785 * Add to list of computed values.
20786 */
20787 if (val == NULL)
20788 val = curVal;
20789 else
20790 xmlSchemaValueAppend(prevVal, curVal);
20791 prevVal = curVal;
20792 curVal = NULL;
20793 }
20794 if (ret != 0) {
20795 if (ret < 0) {
20796 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20797 "validating an item of list simple type");
20798 goto internal_error;
20799 }
20800 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20801 break;
20802 }
20803 cur = end;
20804 } while (*cur != 0);
20805 FREE_AND_NULL(tmpValue);
20806 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20807 /*
20808 * Apply facets (pattern, enumeration).
20809 */
20810 ret = xmlSchemaValidateFacets(actxt, node, type,
20811 XML_SCHEMAS_UNKNOWN, value, val,
20812 len, fireErrors);
20813 if (ret != 0) {
20814 if (ret < 0) {
20815 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20816 "validating facets of list simple type");
20817 goto internal_error;
20818 }
20819 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
20820 }
20821 }
20822 if (fireErrors && (ret > 0)) {
20823 /*
20824 * Report the normalized value.
20825 */
20826 normalize = 1;
20827 NORMALIZE(type);
20828 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20829 }
20830 } else if (VARIETY_UNION(type)) {
20831 xmlSchemaTypeLinkPtr memberLink;
20832 /*
20833 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
20834 * not apply directly; however, the normalization behavior of ·union·
20835 * types is controlled by the value of whiteSpace on that one of the
20836 * ·memberTypes· against which the ·union· is successfully validated.
20837 *
20838 * This means that the value is normalized by the first validating
20839 * member type, then the facets of the union type are applied. This
20840 * needs changing of the value!
20841 */
20842
20843 /*
20844 * 1.2.3 if {variety} is ·union· then the string must ·match· a
20845 * literal in the ·lexical space· of at least one member of
20846 * {member type definitions}
20847 */
20848 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
20849 if (memberLink == NULL) {
20850 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20851 "union simple type has no member types");
20852 goto internal_error;
20853 }
20854 /*
20855 * Always normalize union type values, since we currently
20856 * cannot store the whitespace information with the value
20857 * itself; otherwise a later value-comparison would be
20858 * not possible.
20859 */
20860 while (memberLink != NULL) {
20861 if (valNeeded)
20862 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20863 memberLink->type, value, &val, 0, 1, 0);
20864 else
20865 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
20866 memberLink->type, value, NULL, 0, 1, 0);
20867 if (ret <= 0)
20868 break;
20869 memberLink = memberLink->next;
20870 }
20871 if (ret != 0) {
20872 if (ret < 0) {
20873 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20874 "validating members of union simple type");
20875 goto internal_error;
20876 }
20877 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20878 }
20879 /*
20880 * Apply facets (pattern, enumeration).
20881 */
20882 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
20883 /*
20884 * The normalization behavior of ·union· types is controlled by
20885 * the value of whiteSpace on that one of the ·memberTypes·
20886 * against which the ·union· is successfully validated.
20887 */
20888 NORMALIZE(memberLink->type);
20889 ret = xmlSchemaValidateFacets(actxt, node, type,
20890 XML_SCHEMAS_UNKNOWN, value, val,
20891 0, fireErrors);
20892 if (ret != 0) {
20893 if (ret < 0) {
20894 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
20895 "validating facets of union simple type");
20896 goto internal_error;
20897 }
20898 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
20899 }
20900 }
20901 if (fireErrors && (ret > 0))
20902 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
20903 }
20904
20905 if (normValue != NULL)
20906 xmlFree(normValue);
20907 if (ret == 0) {
20908 if (retVal != NULL)
20909 *retVal = val;
20910 else if (val != NULL)
20911 xmlSchemaFreeValue(val);
20912 } else if (val != NULL)
20913 xmlSchemaFreeValue(val);
20914 return (ret);
20915internal_error:
20916 if (normValue != NULL)
20917 xmlFree(normValue);
20918 if (val != NULL)
20919 xmlSchemaFreeValue(val);
20920 return (-1);
20921}
20922
20923static int
20924xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
20925 const xmlChar *value,
20926 const xmlChar **nsName,
20927 const xmlChar **localName)
20928{
20929 int ret = 0;
20930
20931 if ((nsName == NULL) || (localName == NULL))
20932 return (-1);
20933 *nsName = NULL;
20934 *localName = NULL;
20935
20936 ret = xmlValidateQName(value, 1);
20937 if (ret == -1)
20938 return (-1);
20939 if (ret > 0) {
20940 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
20941 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20942 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
20943 return (1);
20944 }
20945 {
20946 xmlChar *local = NULL;
20947 xmlChar *prefix;
20948
20949 /*
20950 * NOTE: xmlSplitQName2 will return a duplicated
20951 * string.
20952 */
20953 local = xmlSplitQName2(value, &prefix);
20954 VAL_CREATE_DICT;
20955 if (local == NULL)
20956 *localName = xmlDictLookup(vctxt->dict, value, -1);
20957 else {
20958 *localName = xmlDictLookup(vctxt->dict, local, -1);
20959 xmlFree(local);
20960 }
20961
20962 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
20963
20964 if (prefix != NULL) {
20965 xmlFree(prefix);
20966 /*
20967 * A namespace must be found if the prefix is NOT NULL.
20968 */
20969 if (*nsName == NULL) {
20970 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
20971 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
20972 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
20973 "The QName value '%s' has no "
20974 "corresponding namespace declaration in scope",
20975 value, NULL);
20976 return (2);
20977 }
20978 }
20979 }
20980 return (0);
20981}
20982
20983static int
20984xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
20985 xmlSchemaAttrInfoPtr iattr,
20986 xmlSchemaTypePtr *localType,
20987 xmlSchemaElementPtr elemDecl)
20988{
20989 int ret = 0;
20990 /*
20991 * cvc-elt (3.3.4) : (4)
20992 * AND
20993 * Schema-Validity Assessment (Element) (cvc-assess-elt)
20994 * (1.2.1.2.1) - (1.2.1.2.4)
20995 * Handle 'xsi:type'.
20996 */
20997 if (localType == NULL)
20998 return (-1);
20999 *localType = NULL;
21000 if (iattr == NULL)
21001 return (0);
21002 else {
21003 const xmlChar *nsName = NULL, *local = NULL;
21004 /*
21005 * TODO: We should report a *warning* that the type was overriden
21006 * by the instance.
21007 */
21008 ACTIVATE_ATTRIBUTE(iattr);
21009 /*
21010 * (cvc-elt) (3.3.4) : (4.1)
21011 * (cvc-assess-elt) (1.2.1.2.2)
21012 */
21013 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
21014 &nsName, &local);
21015 if (ret != 0) {
21016 if (ret < 0) {
21017 VERROR_INT("xmlSchemaValidateElementByDeclaration",
21018 "calling xmlSchemaQNameExpand() to validate the "
21019 "attribute 'xsi:type'");
21020 goto internal_error;
21021 }
21022 goto exit;
21023 }
21024 /*
21025 * (cvc-elt) (3.3.4) : (4.2)
21026 * (cvc-assess-elt) (1.2.1.2.3)
21027 */
21028 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
21029 if (*localType == NULL) {
21030 xmlChar *str = NULL;
21031
21032 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21033 XML_SCHEMAV_CVC_ELT_4_2, NULL,
21034 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21035 "The QName value '%s' of the xsi:type attribute does not "
21036 "resolve to a type definition",
21037 xmlSchemaFormatQName(&str, nsName, local), NULL);
21038 FREE_AND_NULL(str);
21039 ret = vctxt->err;
21040 goto exit;
21041 }
21042 if (elemDecl != NULL) {
21043 int set = 0;
21044
21045 /*
21046 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
21047 * "The ·local type definition· must be validly
21048 * derived from the {type definition} given the union of
21049 * the {disallowed substitutions} and the {type definition}'s
21050 * {prohibited substitutions}, as defined in
21051 * Type Derivation OK (Complex) (§3.4.6)
21052 * (if it is a complex type definition),
21053 * or given {disallowed substitutions} as defined in Type
21054 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21055 * definition)."
21056 *
21057 * {disallowed substitutions}: the "block" on the element decl.
21058 * {prohibited substitutions}: the "block" on the type def.
21059 */
21060 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21061 (elemDecl->subtypes->flags &
21062 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21063 set |= SUBSET_EXTENSION;
21064
21065 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21066 (elemDecl->subtypes->flags &
21067 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21068 set |= SUBSET_RESTRICTION;
21069
21070 if (xmlSchemaCheckCOSDerivedOK(*localType,
21071 elemDecl->subtypes, set) != 0) {
21072 xmlChar *str = NULL;
21073
21074 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21075 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
21076 "The type definition '%s', specified by xsi:type, is "
21077 "blocked or not validly derived from the type definition "
21078 "of the element declaration",
21079 xmlSchemaFormatQName(&str,
21080 (*localType)->targetNamespace,
21081 (*localType)->name),
21082 NULL);
21083 FREE_AND_NULL(str);
21084 ret = vctxt->err;
21085 *localType = NULL;
21086 }
21087 }
21088 }
21089exit:
21090 ACTIVATE_ELEM;
21091 return (ret);
21092internal_error:
21093 ACTIVATE_ELEM;
21094 return (-1);
21095}
21096
21097static int
21098xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21099{
21100 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21101 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21102
21103 /*
21104 * cvc-elt (3.3.4) : 1
21105 */
21106 if (elemDecl == NULL) {
21107 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21108 "No matching declaration available");
21109 return (vctxt->err);
21110 }
21111 /*
21112 * cvc-elt (3.3.4) : 2
21113 */
21114 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21115 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21116 "The element declaration is abstract");
21117 return (vctxt->err);
21118 }
21119 if (actualType == NULL) {
21120 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21121 "The type definition is absent");
21122 return (XML_SCHEMAV_CVC_TYPE_1);
21123 }
21124 if (vctxt->nbAttrInfos != 0) {
21125 int ret;
21126 xmlSchemaAttrInfoPtr iattr;
21127 /*
21128 * cvc-elt (3.3.4) : 3
21129 * Handle 'xsi:nil'.
21130 */
21131 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21132 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21133 if (iattr) {
21134 ACTIVATE_ATTRIBUTE(iattr);
21135 /*
21136 * Validate the value.
21137 */
21138 ret = xmlSchemaVCheckCVCSimpleType(
21139 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21140 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21141 iattr->value, &(iattr->val), 1, 0, 0);
21142 ACTIVATE_ELEM;
21143 if (ret < 0) {
21144 VERROR_INT("xmlSchemaValidateElemDecl",
21145 "calling xmlSchemaVCheckCVCSimpleType() to "
21146 "validate the attribute 'xsi:nil'");
21147 return (-1);
21148 }
21149 if (ret == 0) {
21150 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21151 /*
21152 * cvc-elt (3.3.4) : 3.1
21153 */
21154 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21155 "The element is not 'nillable'");
21156 /* Does not return an error on purpose. */
21157 } else {
21158 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21159 /*
21160 * cvc-elt (3.3.4) : 3.2.2
21161 */
21162 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21163 (elemDecl->value != NULL)) {
21164 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21165 "The element cannot be 'nilled' because "
21166 "there is a fixed value constraint defined "
21167 "for it");
21168 /* Does not return an error on purpose. */
21169 } else
21170 vctxt->inode->flags |=
21171 XML_SCHEMA_ELEM_INFO_NILLED;
21172 }
21173 }
21174 }
21175 }
21176 /*
21177 * cvc-elt (3.3.4) : 4
21178 * Handle 'xsi:type'.
21179 */
21180 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21181 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21182 if (iattr) {
21183 xmlSchemaTypePtr localType = NULL;
21184
21185 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21186 elemDecl);
21187 if (ret != 0) {
21188 if (ret == -1) {
21189 VERROR_INT("xmlSchemaValidateElemDecl",
21190 "calling xmlSchemaProcessXSIType() to "
21191 "process the attribute 'xsi:type'");
21192 return (-1);
21193 }
21194 /* Does not return an error on purpose. */
21195 }
21196 if (localType != NULL) {
21197 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21198 actualType = localType;
21199 }
21200 }
21201 }
21202 /*
21203 * IDC: Register identity-constraint XPath matchers.
21204 */
21205 if ((elemDecl->idcs != NULL) &&
21206 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21207 return (-1);
21208 /*
21209 * No actual type definition.
21210 */
21211 if (actualType == NULL) {
21212 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21213 "The type definition is absent");
21214 return (XML_SCHEMAV_CVC_TYPE_1);
21215 }
21216 /*
21217 * Remember the actual type definition.
21218 */
21219 vctxt->inode->typeDef = actualType;
21220
21221 return (0);
21222}
21223
21224static int
21225xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21226{
21227 xmlSchemaAttrInfoPtr iattr;
21228 int ret = 0, i;
21229
21230 /*
21231 * SPEC cvc-type (3.1.1)
21232 * "The attributes of must be empty, excepting those whose namespace
21233 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21234 * whose local name is one of type, nil, schemaLocation or
21235 * noNamespaceSchemaLocation."
21236 */
21237 if (vctxt->nbAttrInfos == 0)
21238 return (0);
21239 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21240 iattr = vctxt->attrInfos[i];
21241 if (! iattr->metaType) {
21242 ACTIVATE_ATTRIBUTE(iattr)
21243 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21244 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21245 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21246 }
21247 }
21248 ACTIVATE_ELEM
21249 return (ret);
21250}
21251
21252/*
21253* Cleanup currently used attribute infos.
21254*/
21255static void
21256xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21257{
21258 int i;
21259 xmlSchemaAttrInfoPtr attr;
21260
21261 if (vctxt->nbAttrInfos == 0)
21262 return;
21263 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21264 attr = vctxt->attrInfos[i];
21265 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21266 if (attr->localName != NULL)
21267 xmlFree((xmlChar *) attr->localName);
21268 if (attr->nsName != NULL)
21269 xmlFree((xmlChar *) attr->nsName);
21270 }
21271 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21272 if (attr->value != NULL)
21273 xmlFree((xmlChar *) attr->value);
21274 }
21275 if (attr->val != NULL) {
21276 xmlSchemaFreeValue(attr->val);
21277 attr->val = NULL;
21278 }
21279 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21280 }
21281 vctxt->nbAttrInfos = 0;
21282}
21283
21284/*
21285* 3.4.4 Complex Type Definition Validation Rules
21286* Element Locally Valid (Complex Type) (cvc-complex-type)
21287* 3.2.4 Attribute Declaration Validation Rules
21288* Validation Rule: Attribute Locally Valid (cvc-attribute)
21289* Attribute Locally Valid (Use) (cvc-au)
21290*
21291* Only "assessed" attribute information items will be visible to
21292* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21293*/
21294static int
21295xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21296{
21297 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21298 xmlSchemaAttributeLinkPtr attrUseLink;
21299 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21300 xmlSchemaAttrInfoPtr attr, tmpAttr;
21301 int i, found, nbAttrs;
21302 int xpathRes = 0, res, wildIDs = 0, fixed;
21303
21304 /*
21305 * SPEC (cvc-attribute)
21306 * (1) "The declaration must not be ·absent· (see Missing
21307 * Sub-components (§5.3) for how this can fail to be
21308 * the case)."
21309 * (2) "Its {type definition} must not be absent."
21310 *
21311 * NOTE (1) + (2): This is not handled here, since we currently do not
21312 * allow validation against schemas which have missing sub-components.
21313 *
21314 * SPEC (cvc-complex-type)
21315 * (3) "For each attribute information item in the element information
21316 * item's [attributes] excepting those whose [namespace name] is
21317 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21318 * [local name] is one of type, nil, schemaLocation or
21319 * noNamespaceSchemaLocation, the appropriate case among the following
21320 * must be true:
21321 *
21322 */
21323 nbAttrs = vctxt->nbAttrInfos;
21324 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21325 attrUseLink = attrUseLink->next) {
21326
21327 found = 0;
21328 attrUse = attrUseLink->attr;
21329 /*
21330 * VAL TODO: Implement a real "attribute use" component.
21331 */
21332 if (attrUse->refDecl != NULL)
21333 attrDecl = attrUse->refDecl;
21334 else
21335 attrDecl = attrUse;
21336 for (i = 0; i < nbAttrs; i++) {
21337 attr = vctxt->attrInfos[i];
21338 /*
21339 * SPEC (cvc-complex-type) (3)
21340 * Skip meta attributes.
21341 */
21342 if (attr->metaType)
21343 continue;
21344 if (attr->localName[0] != attrDecl->name[0])
21345 continue;
21346 if (!xmlStrEqual(attr->localName, attrDecl->name))
21347 continue;
21348 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21349 continue;
21350 found = 1;
21351 /*
21352 * SPEC (cvc-complex-type)
21353 * (3.1) "If there is among the {attribute uses} an attribute
21354 * use with an {attribute declaration} whose {name} matches
21355 * the attribute information item's [local name] and whose
21356 * {target namespace} is identical to the attribute information
21357 * item's [namespace name] (where an ·absent· {target namespace}
21358 * is taken to be identical to a [namespace name] with no value),
21359 * then the attribute information must be ·valid· with respect
21360 * to that attribute use as per Attribute Locally Valid (Use)
21361 * (§3.5.4). In this case the {attribute declaration} of that
21362 * attribute use is the ·context-determined declaration· for the
21363 * attribute information item with respect to Schema-Validity
21364 * Assessment (Attribute) (§3.2.4) and
21365 * Assessment Outcome (Attribute) (§3.2.5).
21366 */
21367 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21368 attr->use = attrUse;
21369 /*
21370 * Context-determined declaration.
21371 */
21372 attr->decl = attrDecl;
21373 attr->typeDef = attrDecl->subtypes;
21374 break;
21375 }
21376
21377 if (found)
21378 continue;
21379
21380 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21381 /*
21382 * Handle non-existent, required attributes.
21383 *
21384 * SPEC (cvc-complex-type)
21385 * (4) "The {attribute declaration} of each attribute use in
21386 * the {attribute uses} whose {required} is true matches one
21387 * of the attribute information items in the element information
21388 * item's [attributes] as per clause 3.1 above."
21389 */
21390 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21391 if (tmpAttr == NULL) {
21392 VERROR_INT(
21393 "xmlSchemaVAttributesComplex",
21394 "calling xmlSchemaGetFreshAttrInfo()");
21395 return (-1);
21396 }
21397 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21398 tmpAttr->use = attrUse;
21399 tmpAttr->decl = attrDecl;
21400 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21401 ((attrUse->defValue != NULL) ||
21402 (attrDecl->defValue != NULL))) {
21403 /*
21404 * Handle non-existent, optional, default/fixed attributes.
21405 */
21406 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21407 if (tmpAttr == NULL) {
21408 VERROR_INT(
21409 "xmlSchemaVAttributesComplex",
21410 "calling xmlSchemaGetFreshAttrInfo()");
21411 return (-1);
21412 }
21413 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21414 tmpAttr->use = attrUse;
21415 tmpAttr->decl = attrDecl;
21416 tmpAttr->typeDef = attrDecl->subtypes;
21417 tmpAttr->localName = attrDecl->name;
21418 tmpAttr->nsName = attrDecl->targetNamespace;
21419 }
21420 }
21421 if (vctxt->nbAttrInfos == 0)
21422 return (0);
21423 /*
21424 * Validate against the wildcard.
21425 */
21426 if (type->attributeWildcard != NULL) {
21427 /*
21428 * SPEC (cvc-complex-type)
21429 * (3.2.1) "There must be an {attribute wildcard}."
21430 */
21431 for (i = 0; i < nbAttrs; i++) {
21432 attr = vctxt->attrInfos[i];
21433 /*
21434 * SPEC (cvc-complex-type) (3)
21435 * Skip meta attributes.
21436 */
21437 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21438 continue;
21439 /*
21440 * SPEC (cvc-complex-type)
21441 * (3.2.2) "The attribute information item must be ·valid· with
21442 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21443 *
21444 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21445 * "... its [namespace name] must be ·valid· with respect to
21446 * the wildcard constraint, as defined in Wildcard allows
21447 * Namespace Name (§3.10.4)."
21448 */
21449 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21450 attr->nsName)) {
21451 /*
21452 * Handle processContents.
21453 *
21454 * SPEC (cvc-wildcard):
21455 * processContents | context-determined declaration:
21456 * "strict" "mustFind"
21457 * "lax" "none"
21458 * "skip" "skip"
21459 */
21460 if (type->attributeWildcard->processContents ==
21461 XML_SCHEMAS_ANY_SKIP) {
21462 /*
21463 * context-determined declaration = "skip"
21464 *
21465 * SPEC PSVI Assessment Outcome (Attribute)
21466 * [validity] = "notKnown"
21467 * [validation attempted] = "none"
21468 */
21469 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21470 continue;
21471 }
21472 /*
21473 * Find an attribute declaration.
21474 */
21475 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21476 attr->localName, attr->nsName);
21477 if (attr->decl != NULL) {
21478 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21479 /*
21480 * SPEC (cvc-complex-type)
21481 * (5) "Let [Definition:] the wild IDs be the set of
21482 * all attribute information item to which clause 3.2
21483 * applied and whose ·validation· resulted in a
21484 * ·context-determined declaration· of mustFind or no
21485 * ·context-determined declaration· at all, and whose
21486 * [local name] and [namespace name] resolve (as
21487 * defined by QName resolution (Instance) (§3.15.4)) to
21488 * an attribute declaration whose {type definition} is
21489 * or is derived from ID. Then all of the following
21490 * must be true:"
21491 */
21492 attr->typeDef = attr->decl->subtypes;
21493 if (xmlSchemaIsDerivedFromBuiltInType(
21494 attr->typeDef, XML_SCHEMAS_ID)) {
21495 /*
21496 * SPEC (5.1) "There must be no more than one
21497 * item in ·wild IDs·."
21498 */
21499 if (wildIDs != 0) {
21500 /* VAL TODO */
21501 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21502 TODO
21503 continue;
21504 }
21505 wildIDs++;
21506 /*
21507 * SPEC (cvc-complex-type)
21508 * (5.2) "If ·wild IDs· is non-empty, there must not
21509 * be any attribute uses among the {attribute uses}
21510 * whose {attribute declaration}'s {type definition}
21511 * is or is derived from ID."
21512 */
21513 for (attrUseLink = type->attributeUses;
21514 attrUseLink != NULL;
21515 attrUseLink = attrUseLink->next) {
21516 if (xmlSchemaIsDerivedFromBuiltInType(
21517 attrUseLink->attr->subtypes,
21518 XML_SCHEMAS_ID)) {
21519 /* VAL TODO */
21520 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
21521 TODO
21522 }
21523 }
21524 }
21525 } else if (type->attributeWildcard->processContents ==
21526 XML_SCHEMAS_ANY_LAX) {
21527 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
21528 /*
21529 * SPEC PSVI Assessment Outcome (Attribute)
21530 * [validity] = "notKnown"
21531 * [validation attempted] = "none"
21532 */
21533 } else {
21534 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
21535 }
21536 }
21537 }
21538 }
21539
21540
21541 if (vctxt->nbAttrInfos == 0)
21542 return (0);
21543
21544 /*
21545 * Validate values, create default attributes, evaluate IDCs.
21546 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021547 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21548 attr = vctxt->attrInfos[i];
21549 /*
21550 * VAL TODO: Note that we won't try to resolve IDCs to
21551 * "lax" and "skip" validated attributes. Check what to
21552 * do in this case.
21553 */
21554 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
21555 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
21556 continue;
21557 /*
21558 * VAL TODO: What to do if the type definition is missing?
21559 */
21560 if (attr->typeDef == NULL) {
21561 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
21562 continue;
21563 }
21564
21565 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021566 fixed = 0;
21567 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021568
21569 if (vctxt->xpathStates != NULL) {
21570 /*
21571 * Evaluate IDCs.
21572 */
21573 xpathRes = xmlSchemaXPathEvaluate(vctxt,
21574 XML_ATTRIBUTE_NODE);
21575 if (xpathRes == -1) {
21576 VERROR_INT("xmlSchemaVAttributesComplex",
21577 "calling xmlSchemaXPathEvaluate()");
21578 goto internal_error;
21579 }
21580 }
21581
21582 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
21583 /*
21584 * Default/fixed attributes.
21585 */
21586 if (xpathRes) {
21587 if (attr->use->defValue == NULL) {
21588 attr->value = (xmlChar *) attr->use->defValue;
21589 attr->val = attr->use->defVal;
21590 } else {
21591 attr->value = (xmlChar *) attr->decl->defValue;
21592 attr->val = attr->decl->defVal;
21593 }
21594 /*
21595 * IDCs will consume the precomputed default value,
21596 * so we need to clone it.
21597 */
21598 if (attr->val == NULL) {
21599 VERROR_INT("xmlSchemaVAttributesComplex",
21600 "default/fixed value on an attribute use was "
21601 "not precomputed");
21602 goto internal_error;
21603 }
21604 attr->val = xmlSchemaCopyValue(attr->val);
21605 if (attr->val == NULL) {
21606 VERROR_INT("xmlSchemaVAttributesComplex",
21607 "calling xmlSchemaCopyValue()");
21608 goto internal_error;
21609 }
21610 }
21611 /*
21612 * PSVI: Add the default attribute to the current element.
21613 * VAL TODO: Should we use the *normalized* value? This currently
21614 * uses the *initial* value.
21615 */
21616 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
21617 (attr->node != NULL) && (attr->node->doc != NULL)) {
21618 xmlChar *normValue;
21619 const xmlChar *value;
21620
21621 value = attr->value;
21622 /*
21623 * Normalize the value.
21624 */
21625 normValue = xmlSchemaNormalizeValue(attr->typeDef,
21626 attr->value);
21627 if (normValue != NULL)
21628 value = BAD_CAST normValue;
21629
21630 if (attr->nsName == NULL) {
21631 if (xmlNewProp(attr->node->parent,
21632 attr->localName, value) == NULL) {
21633 VERROR_INT("xmlSchemaVAttributesComplex",
21634 "callling xmlNewProp()");
21635 if (normValue != NULL)
21636 xmlFree(normValue);
21637 goto internal_error;
21638 }
21639 } else {
21640 xmlNsPtr ns;
21641
21642 ns = xmlSearchNsByHref(attr->node->doc,
21643 attr->node->parent, attr->nsName);
21644 if (ns == NULL) {
21645 xmlChar prefix[12];
21646 int counter = 0;
21647
21648 /*
21649 * Create a namespace declaration on the validation
21650 * root node if no namespace declaration is in scope.
21651 */
21652 do {
21653 snprintf((char *) prefix, 12, "p%d", counter++);
21654 ns = xmlSearchNs(attr->node->doc,
21655 attr->node->parent, BAD_CAST prefix);
21656 if (counter > 1000) {
21657 VERROR_INT(
21658 "xmlSchemaVAttributesComplex",
21659 "could not compute a ns prefix for a "
21660 "default/fixed attribute");
21661 if (normValue != NULL)
21662 xmlFree(normValue);
21663 goto internal_error;
21664 }
21665 } while (ns != NULL);
21666 ns = xmlNewNs(vctxt->validationRoot,
21667 attr->nsName, BAD_CAST prefix);
21668 }
21669 xmlNewNsProp(attr->node->parent, ns,
21670 attr->localName, value);
21671 }
21672 if (normValue != NULL)
21673 xmlFree(normValue);
21674 }
21675 /*
21676 * Go directly to IDC evaluation.
21677 */
21678 goto eval_idcs;
21679 }
21680 /*
21681 * Validate the value.
21682 */
21683 if (vctxt->value != NULL) {
21684 /*
21685 * Free last computed value; just for safety reasons.
21686 */
21687 xmlSchemaFreeValue(vctxt->value);
21688 vctxt->value = NULL;
21689 }
21690 /*
21691 * Note that the attribute *use* can be unavailable, if
21692 * the attribute was a wild attribute.
21693 */
21694 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
21695 ((attr->use != NULL) &&
21696 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
21697 fixed = 1;
21698 else
21699 fixed = 0;
21700 /*
21701 * SPEC (cvc-attribute)
21702 * (3) "The item's ·normalized value· must be locally ·valid·
21703 * with respect to that {type definition} as per
21704 * String Valid (§3.14.4)."
21705 *
21706 * VAL TODO: Do we already have the
21707 * "normalized attribute value" here?
21708 */
21709 if (xpathRes || fixed) {
21710 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
21711 /*
21712 * Request a computed value.
21713 */
21714 res = xmlSchemaVCheckCVCSimpleType(
21715 (xmlSchemaAbstractCtxtPtr) vctxt,
21716 attr->node, attr->typeDef, attr->value, &(attr->val),
21717 1, 1, 0);
21718 } else {
21719 res = xmlSchemaVCheckCVCSimpleType(
21720 (xmlSchemaAbstractCtxtPtr) vctxt,
21721 attr->node, attr->typeDef, attr->value, NULL,
21722 1, 0, 0);
21723 }
21724
21725 if (res != 0) {
21726 if (res == -1) {
21727 VERROR_INT("xmlSchemaVAttributesComplex",
21728 "calling xmlSchemaStreamValidateSimpleTypeValue()");
21729 goto internal_error;
21730 }
21731 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
21732 /*
21733 * SPEC PSVI Assessment Outcome (Attribute)
21734 * [validity] = "invalid"
21735 */
21736 goto eval_idcs;
21737 }
21738
21739 if (fixed) {
21740 int ws;
21741 /*
21742 * SPEC Attribute Locally Valid (Use) (cvc-au)
21743 * "For an attribute information item to be·valid·
21744 * with respect to an attribute use its *normalized*
21745 * value· must match the *canonical* lexical
21746 * representation of the attribute use's {value
21747 * constraint}value, if it is present and fixed."
21748 *
21749 * VAL TODO: The requirement for the *canonical* value
21750 * will be removed in XML Schema 1.1.
21751 */
21752 /*
21753 * SPEC Attribute Locally Valid (cvc-attribute)
21754 * (4) "The item's *actual* value· must match the *value* of
21755 * the {value constraint}, if it is present and fixed."
21756 */
21757 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
21758 if (attr->val == NULL) {
21759 /* VAL TODO: A value was not precomputed. */
21760 TODO
21761 goto eval_idcs;
21762 }
21763 if ((attr->use != NULL) &&
21764 (attr->use->defValue != NULL)) {
21765 if (attr->use->defVal == NULL) {
21766 /* VAL TODO: A default value was not precomputed. */
21767 TODO
21768 goto eval_idcs;
21769 }
21770 attr->vcValue = attr->use->defValue;
21771 /*
21772 if (xmlSchemaCompareValuesWhtsp(attr->val,
21773 (xmlSchemaWhitespaceValueType) ws,
21774 attr->use->defVal,
21775 (xmlSchemaWhitespaceValueType) ws) != 0) {
21776 */
21777 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
21778 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21779 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021780 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021781 /* VAL TODO: A default value was not precomputed. */
21782 TODO
21783 goto eval_idcs;
21784 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021785 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021786 /*
21787 if (xmlSchemaCompareValuesWhtsp(attr->val,
21788 (xmlSchemaWhitespaceValueType) ws,
21789 attrDecl->defVal,
21790 (xmlSchemaWhitespaceValueType) ws) != 0) {
21791 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000021792 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021793 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
21794 }
21795 /*
21796 * [validity] = "valid"
21797 */
21798 }
21799eval_idcs:
21800 /*
21801 * Evaluate IDCs.
21802 */
21803 if (xpathRes) {
21804 if (xmlSchemaXPathProcessHistory(vctxt,
21805 vctxt->depth +1) == -1) {
21806 VERROR_INT("xmlSchemaVAttributesComplex",
21807 "calling xmlSchemaXPathEvaluate()");
21808 goto internal_error;
21809 }
21810 }
21811 }
21812
21813 /*
21814 * Report errors.
21815 */
21816 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21817 attr = vctxt->attrInfos[i];
21818 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
21819 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
21820 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
21821 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
21822 continue;
21823 ACTIVATE_ATTRIBUTE(attr);
21824 switch (attr->state) {
21825 case XML_SCHEMAS_ATTR_ERR_MISSING: {
21826 xmlChar *str = NULL;
21827 ACTIVATE_ELEM;
21828 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21829 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
21830 "The attribute '%s' is required but missing",
21831 xmlSchemaFormatQName(&str,
21832 attr->decl->targetNamespace,
21833 attr->decl->name),
21834 NULL);
21835 FREE_AND_NULL(str)
21836 break;
21837 }
21838 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
21839 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
21840 "The type definition is absent");
21841 break;
21842 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
21843 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21844 XML_SCHEMAV_CVC_AU, NULL, NULL,
21845 "The value '%s' does not match the fixed "
21846 "value constraint '%s'",
21847 attr->value, attr->vcValue);
21848 break;
21849 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
21850 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
21851 "No matching global attribute declaration available, but "
21852 "demanded by the strict wildcard");
21853 break;
21854 case XML_SCHEMAS_ATTR_UNKNOWN:
21855 if (attr->metaType)
21856 break;
21857 /*
21858 * MAYBE VAL TODO: One might report different error messages
21859 * for the following errors.
21860 */
21861 if (type->attributeWildcard == NULL) {
21862 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21863 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
21864 } else {
21865 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21866 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
21867 }
21868 break;
21869 default:
21870 break;
21871 }
21872 }
21873
21874 ACTIVATE_ELEM;
21875 return (0);
21876internal_error:
21877 ACTIVATE_ELEM;
21878 return (-1);
21879}
21880
21881static int
21882xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
21883 int *skip)
21884{
21885 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
21886 /*
21887 * The namespace of the element was already identified to be
21888 * matching the wildcard.
21889 */
21890 if ((skip == NULL) || (wild == NULL) ||
21891 (wild->type != XML_SCHEMA_TYPE_ANY)) {
21892 VERROR_INT("xmlSchemaValidateElemWildcard",
21893 "bad arguments");
21894 return (-1);
21895 }
21896 *skip = 0;
21897 if (wild->negNsSet != NULL) {
21898 /*
21899 * URGENT VAL TODO: Fix the content model to reject
21900 * "##other" wildcards.
21901 */
21902 if (xmlSchemaCheckCVCWildcardNamespace(wild,
21903 vctxt->inode->nsName) != 0) {
21904 if ((wild->minOccurs == 1) && (wild->maxOccurs == 1)) {
21905 xmlSchemaNodeInfoPtr pinode = vctxt->elemInfos[vctxt->depth -1];
21906 /*
21907 * VAL TODO: Workaround possible *only* if minOccurs and
21908 * maxOccurs are 1.
21909 */
21910 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21911 /* VAL TODO: error code? */
21912 XML_SCHEMAV_ELEMENT_CONTENT, NULL,
21913 (xmlSchemaTypePtr) wild,
21914 "This element is not accepted by the wildcard",
21915 0, 0, NULL);
21916 vctxt->skipDepth = vctxt->depth;
21917 if ((pinode->flags &
21918 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0)
21919 pinode->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
21920 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
21921 return (XML_SCHEMAV_ELEMENT_CONTENT);
21922 }
21923 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21924 *skip = 1;
21925 return (0);
21926 }
21927 vctxt->inode->typeDef =
21928 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21929 return (0);
21930 }
21931 }
21932 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
21933 /*
21934 * URGENT VAL TODO: Either we need to position the stream to the
21935 * next sibling, or walk the whole subtree.
21936 */
21937 *skip = 1;
21938 return (0);
21939 }
21940 {
21941 xmlSchemaElementPtr decl = NULL;
21942
21943 decl = xmlHashLookup3(vctxt->schema->elemDecl,
21944 vctxt->inode->localName, vctxt->inode->nsName,
21945 NULL);
21946 if (decl != NULL) {
21947 vctxt->inode->decl = decl;
21948 return (0);
21949 }
21950 }
21951 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
21952 /* VAL TODO: Change to proper error code. */
21953 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
21954 "No matching global element declaration available, but "
21955 "demanded by the strict wildcard");
21956 return (vctxt->err);
21957 }
21958 if (vctxt->nbAttrInfos != 0) {
21959 xmlSchemaAttrInfoPtr iattr;
21960 /*
21961 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21962 * (1.2.1.2.1) - (1.2.1.2.3 )
21963 *
21964 * Use the xsi:type attribute for the type definition.
21965 */
21966 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21967 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21968 if (iattr != NULL) {
21969 if (xmlSchemaProcessXSIType(vctxt, iattr,
21970 &(vctxt->inode->typeDef), NULL) == -1) {
21971 VERROR_INT("xmlSchemaValidateElemWildcard",
21972 "calling xmlSchemaProcessXSIType() to "
21973 "process the attribute 'xsi:nil'");
21974 return (-1);
21975 }
21976 /*
21977 * Don't return an error on purpose.
21978 */
21979 return (0);
21980 }
21981 }
21982 /*
21983 * SPEC Validation Rule: Schema-Validity Assessment (Element)
21984 *
21985 * Fallback to "anyType".
21986 */
21987 vctxt->inode->typeDef =
21988 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
21989 return (0);
21990}
21991
21992/*
21993* xmlSchemaCheckCOSValidDefault:
21994*
21995* This will be called if: not nilled, no content and a default/fixed
21996* value is provided.
21997*/
21998
21999static int
22000xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
22001 const xmlChar *value,
22002 xmlSchemaValPtr *val)
22003{
22004 int ret = 0;
22005 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22006
22007 /*
22008 * cos-valid-default:
22009 * Schema Component Constraint: Element Default Valid (Immediate)
22010 * For a string to be a valid default with respect to a type
22011 * definition the appropriate case among the following must be true:
22012 */
22013 if IS_COMPLEX_TYPE(inode->typeDef) {
22014 /*
22015 * Complex type.
22016 *
22017 * SPEC (2.1) "its {content type} must be a simple type definition
22018 * or mixed."
22019 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
22020 * type}'s particle must be ·emptiable· as defined by
22021 * Particle Emptiable (§3.9.6)."
22022 */
22023 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
22024 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
22025 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
22026 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
22027 /* NOTE that this covers (2.2.2) as well. */
22028 VERROR(ret, NULL,
22029 "For a string to be a valid default, the type definition "
22030 "must be a simple type or a complex type with simple content "
22031 "or mixed content and a particle emptiable");
22032 return(ret);
22033 }
22034 }
22035 /*
22036 * 1 If the type definition is a simple type definition, then the string
22037 * must be ·valid· with respect to that definition as defined by String
22038 * Valid (§3.14.4).
22039 *
22040 * AND
22041 *
22042 * 2.2.1 If the {content type} is a simple type definition, then the
22043 * string must be ·valid· with respect to that simple type definition
22044 * as defined by String Valid (§3.14.4).
22045 */
22046 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22047
22048 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22049 NULL, inode->typeDef, value, val, 1, 1, 0);
22050
22051 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22052
22053 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22054 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
22055 }
22056 if (ret < 0) {
22057 VERROR_INT("xmlSchemaCheckCOSValidDefault",
22058 "calling xmlSchemaVCheckCVCSimpleType()");
22059 }
22060 return (ret);
22061}
22062
22063static void
22064xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22065 const xmlChar * name ATTRIBUTE_UNUSED,
22066 xmlSchemaElementPtr item,
22067 xmlSchemaNodeInfoPtr inode)
22068{
22069 inode->decl = item;
22070#ifdef DEBUG_CONTENT
22071 {
22072 xmlChar *str = NULL;
22073
22074 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
22075 xmlGenericError(xmlGenericErrorContext,
22076 "AUTOMATON callback for '%s' [declaration]\n",
22077 xmlSchemaFormatQName(&str,
22078 inode->localName, inode->nsName));
22079 } else {
22080 xmlGenericError(xmlGenericErrorContext,
22081 "AUTOMATON callback for '%s' [wildcard]\n",
22082 xmlSchemaFormatQName(&str,
22083 inode->localName, inode->nsName));
22084
22085 }
22086 FREE_AND_NULL(str)
22087 }
22088#endif
22089}
22090
22091static int
22092xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022093{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022094 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22095 if (vctxt->inode == NULL) {
22096 VERROR_INT("xmlSchemaValidatorPushElem",
22097 "calling xmlSchemaGetFreshElemInfo()");
22098 return (-1);
22099 }
22100 vctxt->nbAttrInfos = 0;
22101 return (0);
22102}
22103
22104static int
22105xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22106 xmlSchemaNodeInfoPtr inode,
22107 xmlSchemaTypePtr type,
22108 const xmlChar *value)
22109{
22110 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22111 return (xmlSchemaVCheckCVCSimpleType(
22112 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22113 type, value, &(inode->val), 1, 1, 0));
22114 else
22115 return (xmlSchemaVCheckCVCSimpleType(
22116 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22117 type, value, NULL, 1, 0, 0));
22118}
22119
22120
22121
22122/*
22123* Process END of element.
22124*/
22125static int
22126xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22127{
22128 int ret = 0;
22129 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22130
22131 if (vctxt->nbAttrInfos != 0)
22132 xmlSchemaClearAttrInfos(vctxt);
22133 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22134 /*
22135 * This element was not expected;
22136 * we will not validate child elements of broken parents.
22137 * Skip validation of all content of the parent.
22138 */
22139 vctxt->skipDepth = vctxt->depth -1;
22140 goto end_elem;
22141 }
22142 if ((inode->typeDef == NULL) ||
22143 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22144 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022145 * 1. the type definition might be missing if the element was
22146 * error prone
22147 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022148 */
22149 goto end_elem;
22150 }
22151 /*
22152 * Check the content model.
22153 */
22154 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22155 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22156
22157 /*
22158 * Workaround for "anyType".
22159 */
22160 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22161 goto character_content;
22162
22163 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22164 xmlChar *values[10];
22165 int terminal, nbval = 10, nbneg;
22166
22167 if (inode->regexCtxt == NULL) {
22168 /*
22169 * Create the regex context.
22170 */
22171 inode->regexCtxt =
22172 xmlRegNewExecCtxt(inode->typeDef->contModel,
22173 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22174 vctxt);
22175 if (inode->regexCtxt == NULL) {
22176 VERROR_INT("xmlSchemaValidatorPopElem",
22177 "failed to create a regex context");
22178 goto internal_error;
22179 }
22180#ifdef DEBUG_AUTOMATA
22181 xmlGenericError(xmlGenericErrorContext,
22182 "AUTOMATON create on '%s'\n", inode->localName);
22183#endif
22184 }
22185 /*
22186 * Get hold of the still expected content, since a further
22187 * call to xmlRegExecPushString() will loose this information.
22188 */
22189 xmlRegExecNextValues(inode->regexCtxt,
22190 &nbval, &nbneg, &values[0], &terminal);
22191 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22192 if (ret <= 0) {
22193 /*
22194 * Still missing something.
22195 */
22196 ret = 1;
22197 inode->flags |=
22198 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22199 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22200 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22201 "Missing child element(s)",
22202 nbval, nbneg, values);
22203#ifdef DEBUG_AUTOMATA
22204 xmlGenericError(xmlGenericErrorContext,
22205 "AUTOMATON missing ERROR on '%s'\n",
22206 inode->localName);
22207#endif
22208 } else {
22209 /*
22210 * Content model is satisfied.
22211 */
22212 ret = 0;
22213#ifdef DEBUG_AUTOMATA
22214 xmlGenericError(xmlGenericErrorContext,
22215 "AUTOMATON succeeded on '%s'\n",
22216 inode->localName);
22217#endif
22218 }
22219
22220 }
22221 }
22222 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22223 goto end_elem;
22224
22225character_content:
22226
22227 if (vctxt->value != NULL) {
22228 xmlSchemaFreeValue(vctxt->value);
22229 vctxt->value = NULL;
22230 }
22231 /*
22232 * Check character content.
22233 */
22234 if (inode->decl == NULL) {
22235 /*
22236 * Speedup if no declaration exists.
22237 */
22238 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22239 ret = xmlSchemaVCheckINodeDataType(vctxt,
22240 inode, inode->typeDef, inode->value);
22241 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22242 ret = xmlSchemaVCheckINodeDataType(vctxt,
22243 inode, inode->typeDef->contentTypeDef,
22244 inode->value);
22245 }
22246 if (ret < 0) {
22247 VERROR_INT("xmlSchemaValidatorPopElem",
22248 "calling xmlSchemaVCheckCVCSimpleType()");
22249 goto internal_error;
22250 }
22251 goto end_elem;
22252 }
22253 /*
22254 * cvc-elt (3.3.4) : 5
22255 * The appropriate case among the following must be true:
22256 */
22257 /*
22258 * cvc-elt (3.3.4) : 5.1
22259 * If the declaration has a {value constraint},
22260 * the item has neither element nor character [children] and
22261 * clause 3.2 has not applied, then all of the following must be true:
22262 */
22263 if ((inode->decl->value != NULL) &&
22264 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22265 (! INODE_NILLED(inode))) {
22266 /*
22267 * cvc-elt (3.3.4) : 5.1.1
22268 * If the ·actual type definition· is a ·local type definition·
22269 * then the canonical lexical representation of the {value constraint}
22270 * value must be a valid default for the ·actual type definition· as
22271 * defined in Element Default Valid (Immediate) (§3.3.6).
22272 */
22273 /*
22274 * NOTE: 'local' above means types aquired by xsi:type.
22275 * NOTE: Although the *canonical* value is stated, it is not
22276 * relevant if canonical or not. Additionally XML Schema 1.1
22277 * will removed this requirement as well.
22278 */
22279 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22280
22281 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22282 inode->decl->value, &(inode->val));
22283 if (ret != 0) {
22284 if (ret < 0) {
22285 VERROR_INT("xmlSchemaValidatorPopElem",
22286 "calling xmlSchemaCheckCOSValidDefault()");
22287 goto internal_error;
22288 }
22289 goto end_elem;
22290 }
22291 /*
22292 * Stop here, to avoid redundant validation of the value
22293 * (see following).
22294 */
22295 goto default_psvi;
22296 }
22297 /*
22298 * cvc-elt (3.3.4) : 5.1.2
22299 * The element information item with the canonical lexical
22300 * representation of the {value constraint} value used as its
22301 * ·normalized value· must be ·valid· with respect to the
22302 * ·actual type definition· as defined by Element Locally Valid (Type)
22303 * (§3.3.4).
22304 */
22305 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22306 ret = xmlSchemaVCheckINodeDataType(vctxt,
22307 inode, inode->typeDef, inode->decl->value);
22308 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22309 ret = xmlSchemaVCheckINodeDataType(vctxt,
22310 inode, inode->typeDef->contentTypeDef,
22311 inode->decl->value);
22312 }
22313 if (ret != 0) {
22314 if (ret < 0) {
22315 VERROR_INT("xmlSchemaValidatorPopElem",
22316 "calling xmlSchemaVCheckCVCSimpleType()");
22317 goto internal_error;
22318 }
22319 goto end_elem;
22320 }
22321
22322default_psvi:
22323 /*
22324 * PSVI: Create a text node on the instance element.
22325 */
22326 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22327 (inode->node != NULL)) {
22328 xmlNodePtr textChild;
22329 xmlChar *normValue;
22330 /*
22331 * VAL TODO: Normalize the value.
22332 */
22333 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22334 inode->decl->value);
22335 if (normValue != NULL) {
22336 textChild = xmlNewText(BAD_CAST normValue);
22337 xmlFree(normValue);
22338 } else
22339 textChild = xmlNewText(inode->decl->value);
22340 if (textChild == NULL) {
22341 VERROR_INT("xmlSchemaValidatorPopElem",
22342 "calling xmlNewText()");
22343 goto internal_error;
22344 } else
22345 xmlAddChild(inode->node, textChild);
22346 }
22347
22348 } else if (! INODE_NILLED(inode)) {
22349 /*
22350 * 5.2.1 The element information item must be ·valid· with respect
22351 * to the ·actual type definition· as defined by Element Locally
22352 * Valid (Type) (§3.3.4).
22353 */
22354 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22355 /*
22356 * SPEC (cvc-type) (3.1)
22357 * "If the type definition is a simple type definition, ..."
22358 * (3.1.3) "If clause 3.2 of Element Locally Valid
22359 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22360 * must be ·valid· with respect to the type definition as defined
22361 * by String Valid (§3.14.4).
22362 */
22363 ret = xmlSchemaVCheckINodeDataType(vctxt,
22364 inode, inode->typeDef, inode->value);
22365 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22366 /*
22367 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22368 * definition, then the element information item must be
22369 * ·valid· with respect to the type definition as per
22370 * Element Locally Valid (Complex Type) (§3.4.4);"
22371 *
22372 * SPEC (cvc-complex-type) (2.2)
22373 * "If the {content type} is a simple type definition, ...
22374 * the ·normalized value· of the element information item is
22375 * ·valid· with respect to that simple type definition as
22376 * defined by String Valid (§3.14.4)."
22377 */
22378 ret = xmlSchemaVCheckINodeDataType(vctxt,
22379 inode, inode->typeDef->contentTypeDef, inode->value);
22380 }
22381 if (ret != 0) {
22382 if (ret < 0) {
22383 VERROR_INT("xmlSchemaValidatorPopElem",
22384 "calling xmlSchemaVCheckCVCSimpleType()");
22385 goto internal_error;
22386 }
22387 goto end_elem;
22388 }
22389 /*
22390 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22391 * not applied, all of the following must be true:
22392 */
22393 if ((inode->decl->value != NULL) &&
22394 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22395
22396 /*
22397 * TODO: We will need a computed value, when comparison is
22398 * done on computed values.
22399 */
22400 /*
22401 * 5.2.2.1 The element information item must have no element
22402 * information item [children].
22403 */
22404 if (inode->flags &
22405 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22406 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22407 VERROR(ret, NULL,
22408 "The content must not containt element nodes since "
22409 "there is a fixed value constraint");
22410 goto end_elem;
22411 } else {
22412 /*
22413 * 5.2.2.2 The appropriate case among the following must
22414 * be true:
22415 */
22416 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22417 /*
22418 * 5.2.2.2.1 If the {content type} of the ·actual type
22419 * definition· is mixed, then the *initial value* of the
22420 * item must match the canonical lexical representation
22421 * of the {value constraint} value.
22422 *
22423 * ... the *initial value* of an element information
22424 * item is the string composed of, in order, the
22425 * [character code] of each character information item in
22426 * the [children] of that element information item.
22427 */
22428 if (! xmlStrEqual(inode->value, inode->decl->value)){
22429 /*
22430 * VAL TODO: Report invalid & expected values as well.
22431 * VAL TODO: Implement the canonical stuff.
22432 */
22433 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22434 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22435 ret, NULL, NULL,
22436 "The initial value '%s' does not match the fixed "
22437 "value constraint '%s'",
22438 inode->value, inode->decl->value);
22439 goto end_elem;
22440 }
22441 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22442 /*
22443 * 5.2.2.2.2 If the {content type} of the ·actual type
22444 * definition· is a simple type definition, then the
22445 * *actual value* of the item must match the canonical
22446 * lexical representation of the {value constraint} value.
22447 */
22448 /*
22449 * VAL TODO: *actual value* is the normalized value, impl.
22450 * this.
22451 * VAL TODO: Report invalid & expected values as well.
22452 * VAL TODO: Implement a comparison with the computed values.
22453 */
22454 if (! xmlStrEqual(inode->value,
22455 inode->decl->value)) {
22456 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22457 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22458 ret, NULL, NULL,
22459 "The actual value '%s' does not match the fixed "
22460 "value constraint '%s'",
22461 inode->value,
22462 inode->decl->value);
22463 goto end_elem;
22464 }
22465 }
22466 }
22467 }
22468 }
22469
22470end_elem:
22471 if (vctxt->depth < 0) {
22472 /* TODO: raise error? */
22473 return (0);
22474 }
22475 if (vctxt->depth == vctxt->skipDepth)
22476 vctxt->skipDepth = -1;
22477 /*
22478 * Evaluate the history of XPath state objects.
22479 */
22480 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22481 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022482 /*
22483 * TODO: 6 The element information item must be ·valid· with respect to each of
22484 * the {identity-constraint definitions} as per Identity-constraint
22485 * Satisfied (§3.11.4).
22486 */
22487 /*
22488 * Validate IDC keyrefs.
22489 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022490 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22491 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022492 /*
22493 * Merge/free the IDC table.
22494 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022495 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022496#ifdef DEBUG_IDC
22497 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022498 inode->nsName,
22499 inode->localName,
22500 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022501#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022502 if (vctxt->depth > 0) {
22503 /*
22504 * Merge the IDC node table with the table of the parent node.
22505 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022506 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22507 goto internal_error;
22508 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022509 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022510 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022511 * Clear the current ielem.
22512 * VAL TODO: Don't free the PSVI IDC tables if they are
22513 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022514 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022515 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022516 /*
22517 * Skip further processing if we are on the validation root.
22518 */
22519 if (vctxt->depth == 0) {
22520 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022521 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022522 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022523 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022524 /*
22525 * Reset the bubbleDepth if needed.
22526 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022527 if (vctxt->aidcs != NULL) {
22528 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22529 do {
22530 if (aidc->bubbleDepth == vctxt->depth) {
22531 /*
22532 * A bubbleDepth of a key/unique IDC matches the current
22533 * depth, this means that we are leaving the scope of the
22534 * top-most keyref IDC.
22535 */
22536 aidc->bubbleDepth = -1;
22537 }
22538 aidc = aidc->next;
22539 } while (aidc != NULL);
22540 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022541 vctxt->depth--;
22542 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000022543 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022544 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022545 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
22546 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022547 return (ret);
22548
22549internal_error:
22550 vctxt->err = -1;
22551 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000022552}
22553
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022554/*
22555* 3.4.4 Complex Type Definition Validation Rules
22556* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
22557*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000022558static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022559xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000022560{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022561 xmlSchemaNodeInfoPtr pielem;
22562 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022563 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000022564
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022565 if (vctxt->depth <= 0) {
22566 VERROR_INT("xmlSchemaValidateChildElem",
22567 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022568 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022569 }
22570 pielem = vctxt->elemInfos[vctxt->depth -1];
22571 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
22572 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022573 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022574 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022575 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022576 if (INODE_NILLED(pielem)) {
22577 /*
22578 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
22579 */
22580 ACTIVATE_PARENT_ELEM;
22581 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
22582 VERROR(ret, NULL,
22583 "Neither character nor element content is allowed, "
22584 "because the element was 'nilled'");
22585 ACTIVATE_ELEM;
22586 goto unexpected_elem;
22587 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022588
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022589 ptype = pielem->typeDef;
22590
22591 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
22592 /*
22593 * Workaround for "anyType": we have currently no content model
22594 * assigned for "anyType", so handle it explicitely.
22595 * "anyType" has an unbounded, lax "any" wildcard.
22596 */
22597 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22598 vctxt->inode->localName,
22599 vctxt->inode->nsName);
22600
22601 if (vctxt->inode->decl == NULL) {
22602 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022603 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022604 * Process "xsi:type".
22605 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022606 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022607 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22608 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22609 if (iattr != NULL) {
22610 ret = xmlSchemaProcessXSIType(vctxt, iattr,
22611 &(vctxt->inode->typeDef), NULL);
22612 if (ret != 0) {
22613 if (ret == -1) {
22614 VERROR_INT("xmlSchemaValidateChildElem",
22615 "calling xmlSchemaProcessXSIType() to "
22616 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022617 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000022618 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022619 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000022620 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022621 } else {
22622 /*
22623 * Fallback to "anyType".
22624 *
22625 * SPEC (cvc-assess-elt)
22626 * "If the item cannot be ·strictly assessed·, [...]
22627 * an element information item's schema validity may be laxly
22628 * assessed if its ·context-determined declaration· is not
22629 * skip by ·validating· with respect to the ·ur-type
22630 * definition· as per Element Locally Valid (Type) (§3.3.4)."
22631 */
22632 vctxt->inode->typeDef =
22633 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022634 }
22635 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022636 return (0);
22637 }
22638
22639 switch (ptype->contentType) {
22640 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022641 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022642 * SPEC (2.1) "If the {content type} is empty, then the
22643 * element information item has no character or element
22644 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022645 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022646 ACTIVATE_PARENT_ELEM
22647 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
22648 VERROR(ret, NULL,
22649 "Element content is not allowed, "
22650 "because the content type is empty");
22651 ACTIVATE_ELEM
22652 goto unexpected_elem;
22653 break;
22654
22655 case XML_SCHEMA_CONTENT_MIXED:
22656 case XML_SCHEMA_CONTENT_ELEMENTS: {
22657 xmlRegExecCtxtPtr regexCtxt;
22658 xmlChar *values[10];
22659 int terminal, nbval = 10, nbneg;
22660
22661 /* VAL TODO: Optimized "anyType" validation.*/
22662
22663 if (ptype->contModel == NULL) {
22664 VERROR_INT("xmlSchemaValidateChildElem",
22665 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022666 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000022667 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022668 /*
22669 * Safety belf for evaluation if the cont. model was already
22670 * examined to be invalid.
22671 */
22672 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
22673 VERROR_INT("xmlSchemaValidateChildElem",
22674 "validating elem, but elem content is already invalid");
22675 return (-1);
22676 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000022677
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022678 regexCtxt = pielem->regexCtxt;
22679 if (regexCtxt == NULL) {
22680 /*
22681 * Create the regex context.
22682 */
22683 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
22684 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22685 vctxt);
22686 if (regexCtxt == NULL) {
22687 VERROR_INT("xmlSchemaValidateChildElem",
22688 "failed to create a regex context");
22689 return (-1);
22690 }
22691 pielem->regexCtxt = regexCtxt;
22692#ifdef DEBUG_AUTOMATA
22693 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
22694 pielem->localName);
22695#endif
22696 }
22697
22698 /*
22699 * SPEC (2.4) "If the {content type} is element-only or mixed,
22700 * then the sequence of the element information item's
22701 * element information item [children], if any, taken in
22702 * order, is ·valid· with respect to the {content type}'s
22703 * particle, as defined in Element Sequence Locally Valid
22704 * (Particle) (§3.9.4)."
22705 */
22706 ret = xmlRegExecPushString2(regexCtxt,
22707 vctxt->inode->localName,
22708 vctxt->inode->nsName,
22709 vctxt->inode);
22710#ifdef DEBUG_AUTOMATA
22711 if (ret < 0)
22712 xmlGenericError(xmlGenericErrorContext,
22713 "AUTOMATON push ERROR for '%s' on '%s'\n",
22714 vctxt->inode->localName, pielem->localName);
22715 else
22716 xmlGenericError(xmlGenericErrorContext,
22717 "AUTOMATON push OK for '%s' on '%s'\n",
22718 vctxt->inode->localName, pielem->localName);
22719#endif
22720 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
22721 VERROR_INT("xmlSchemaValidateChildElem",
22722 "calling xmlRegExecPushString2()");
22723 return (-1);
22724 }
22725 if (ret < 0) {
22726 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
22727 &values[0], &terminal);
22728 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22729 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
22730 "This element is not expected",
22731 nbval, nbneg, values);
22732 ret = vctxt->err;
22733 goto unexpected_elem;
22734 } else
22735 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000022736 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022737 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022738 case XML_SCHEMA_CONTENT_SIMPLE:
22739 case XML_SCHEMA_CONTENT_BASIC:
22740 ACTIVATE_PARENT_ELEM
22741 if (IS_COMPLEX_TYPE(ptype)) {
22742 /*
22743 * SPEC (cvc-complex-type) (2.2)
22744 * "If the {content type} is a simple type definition, then
22745 * the element information item has no element information
22746 * item [children], ..."
22747 */
22748 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
22749 VERROR(ret, NULL, "Element content is not allowed, "
22750 "because the content type is a simple type definition");
22751 } else {
22752 /*
22753 * SPEC (cvc-type) (3.1.2) "The element information item must
22754 * have no element information item [children]."
22755 */
22756 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
22757 VERROR(ret, NULL, "Element content is not allowed, "
22758 "because the type definition is simple");
22759 }
22760 ACTIVATE_ELEM
22761 ret = vctxt->err;
22762 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022763 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022764
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022765 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022766 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022767 }
22768 return (ret);
22769unexpected_elem:
22770 /*
22771 * Pop this element and set the skipDepth to skip
22772 * all further content of the parent element.
22773 */
22774 vctxt->skipDepth = vctxt->depth;
22775 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
22776 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22777 return (ret);
22778}
22779
22780#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
22781#define XML_SCHEMA_PUSH_TEXT_CREATED 2
22782#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
22783
22784static int
22785xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
22786 int nodeType, const xmlChar *value, int len,
22787 int mode, int *consumed)
22788{
22789 /*
22790 * Unfortunately we have to duplicate the text sometimes.
22791 * OPTIMIZE: Maybe we could skip it, if:
22792 * 1. content type is simple
22793 * 2. whitespace is "collapse"
22794 * 3. it consists of whitespace only
22795 *
22796 * Process character content.
22797 */
22798 if (consumed != NULL)
22799 *consumed = 0;
22800 if (INODE_NILLED(vctxt->inode)) {
22801 /*
22802 * SPEC cvc-elt (3.3.4 - 3.2.1)
22803 * "The element information item must have no character or
22804 * element information item [children]."
22805 */
22806 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
22807 "Neither character nor element content is allowed "
22808 "because the element is 'nilled'");
22809 return (vctxt->err);
22810 }
22811 /*
22812 * SPEC (2.1) "If the {content type} is empty, then the
22813 * element information item has no character or element
22814 * information item [children]."
22815 */
22816 if (vctxt->inode->typeDef->contentType ==
22817 XML_SCHEMA_CONTENT_EMPTY) {
22818 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
22819 "Character content is not allowed, "
22820 "because the content type is empty");
22821 return (vctxt->err);
22822 }
22823
22824 if (vctxt->inode->typeDef->contentType ==
22825 XML_SCHEMA_CONTENT_ELEMENTS) {
22826 if ((nodeType != XML_TEXT_NODE) ||
22827 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
22828 /*
22829 * SPEC cvc-complex-type (2.3)
22830 * "If the {content type} is element-only, then the
22831 * element information item has no character information
22832 * item [children] other than those whose [character
22833 * code] is defined as a white space in [XML 1.0 (Second
22834 * Edition)]."
22835 */
22836 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
22837 "Character content other than whitespace is not allowed "
22838 "because the content type is 'element-only'");
22839 return (vctxt->err);
22840 }
22841 return (0);
22842 }
22843
22844 if ((value == NULL) || (value[0] == 0))
22845 return (0);
22846 /*
22847 * Save the value.
22848 * NOTE that even if the content type is *mixed*, we need the
22849 * *initial value* for default/fixed value constraints.
22850 */
22851 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
22852 ((vctxt->inode->decl == NULL) ||
22853 (vctxt->inode->decl->value == NULL)))
22854 return (0);
22855
22856 if (vctxt->inode->value == NULL) {
22857 /*
22858 * Set the value.
22859 */
22860 switch (mode) {
22861 case XML_SCHEMA_PUSH_TEXT_PERSIST:
22862 /*
22863 * When working on a tree.
22864 */
22865 vctxt->inode->value = value;
22866 break;
22867 case XML_SCHEMA_PUSH_TEXT_CREATED:
22868 /*
22869 * When working with the reader.
22870 * The value will be freed by the element info.
22871 */
22872 vctxt->inode->value = value;
22873 if (consumed != NULL)
22874 *consumed = 1;
22875 vctxt->inode->flags |=
22876 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22877 break;
22878 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
22879 /*
22880 * When working with SAX.
22881 * The value will be freed by the element info.
22882 */
22883 if (len != -1)
22884 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
22885 else
22886 vctxt->inode->value = BAD_CAST xmlStrdup(value);
22887 vctxt->inode->flags |=
22888 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22889 break;
22890 default:
22891 break;
22892 }
22893 } else {
22894 /*
22895 * Concat the value.
22896 */
22897 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000022898 vctxt->inode->value = BAD_CAST xmlStrncat(
22899 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022900 } else {
22901 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022902 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022903 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
22904 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022905 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022906
22907 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000022908}
22909
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022910static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022911xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000022912{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022913 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000022914
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022915 if ((vctxt->skipDepth != -1) &&
22916 (vctxt->depth >= vctxt->skipDepth)) {
22917 VERROR_INT("xmlSchemaValidateElem",
22918 "in skip-state");
22919 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000022920 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022921 if (vctxt->xsiAssemble) {
22922 if (xmlSchemaAssembleByXSI(vctxt) == -1)
22923 goto internal_error;
22924 }
22925 if (vctxt->depth > 0) {
22926 /*
22927 * Validate this element against the content model
22928 * of the parent.
22929 */
22930 ret = xmlSchemaValidateChildElem(vctxt);
22931 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022932 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022933 VERROR_INT("xmlSchemaValidateElem",
22934 "calling xmlSchemaStreamValidateChildElement()");
22935 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022936 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022937 goto exit;
22938 }
22939 if (vctxt->depth == vctxt->skipDepth)
22940 goto exit;
22941 if ((vctxt->inode->decl == NULL) &&
22942 (vctxt->inode->typeDef == NULL)) {
22943 VERROR_INT("xmlSchemaValidateElem",
22944 "the child element was valid but neither the "
22945 "declaration nor the type was set");
22946 goto internal_error;
22947 }
22948 } else {
22949 /*
22950 * Get the declaration of the validation root.
22951 */
22952 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
22953 vctxt->inode->localName,
22954 vctxt->inode->nsName);
22955 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000022956 ret = XML_SCHEMAV_CVC_ELT_1;
22957 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022958 "No matching global declaration available "
22959 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022960 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022961 }
22962 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000022963
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022964 if (vctxt->inode->decl == NULL)
22965 goto type_validation;
22966
22967 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
22968 int skip;
22969 /*
22970 * Wildcards.
22971 */
22972 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
22973 if (ret != 0) {
22974 if (ret < 0) {
22975 VERROR_INT("xmlSchemaValidateElem",
22976 "calling xmlSchemaValidateElemWildcard()");
22977 goto internal_error;
22978 }
22979 goto exit;
22980 }
22981 if (skip) {
22982 vctxt->skipDepth = vctxt->depth;
22983 goto exit;
22984 }
22985 /*
22986 * The declaration might be set by the wildcard validation,
22987 * when the processContents is "lax" or "strict".
22988 */
22989 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
22990 /*
22991 * Clear the "decl" field to not confuse further processing.
22992 */
22993 vctxt->inode->decl = NULL;
22994 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000022995 }
Daniel Veillard4255d502002-04-16 15:50:10 +000022996 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022997 /*
22998 * Validate against the declaration.
22999 */
23000 ret = xmlSchemaValidateElemDecl(vctxt);
23001 if (ret != 0) {
23002 if (ret < 0) {
23003 VERROR_INT("xmlSchemaValidateElem",
23004 "calling xmlSchemaValidateElemDecl()");
23005 goto internal_error;
23006 }
23007 goto exit;
23008 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023009 /*
23010 * Validate against the type definition.
23011 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023012type_validation:
23013
23014 if (vctxt->inode->typeDef == NULL) {
23015 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
23016 ret = XML_SCHEMAV_CVC_TYPE_1;
23017 VERROR(ret, NULL,
23018 "The type definition is absent");
23019 goto exit;
23020 }
23021 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
23022 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
23023 ret = XML_SCHEMAV_CVC_TYPE_2;
23024 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023025 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023026 goto exit;
23027 }
23028 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023029 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023030 * during validation against the declaration. This must be done
23031 * _before_ attribute validation.
23032 */
23033 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
23034 if (ret == -1) {
23035 VERROR_INT("xmlSchemaValidateElem",
23036 "calling xmlSchemaXPathEvaluate()");
23037 goto internal_error;
23038 }
23039 /*
23040 * Validate attributes.
23041 */
23042 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
23043 if ((vctxt->nbAttrInfos != 0) ||
23044 (vctxt->inode->typeDef->attributeUses != NULL)) {
23045
23046 ret = xmlSchemaVAttributesComplex(vctxt);
23047 }
23048 } else if (vctxt->nbAttrInfos != 0) {
23049
23050 ret = xmlSchemaVAttributesSimple(vctxt);
23051 }
23052 /*
23053 * Clear registered attributes.
23054 */
23055 if (vctxt->nbAttrInfos != 0)
23056 xmlSchemaClearAttrInfos(vctxt);
23057 if (ret == -1) {
23058 VERROR_INT("xmlSchemaValidateElem",
23059 "calling attributes validation");
23060 goto internal_error;
23061 }
23062 /*
23063 * Don't return an error if attributes are invalid on purpose.
23064 */
23065 ret = 0;
23066
23067exit:
23068 if (ret != 0)
23069 vctxt->skipDepth = vctxt->depth;
23070 return (ret);
23071internal_error:
23072 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023073}
23074
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023075#ifdef XML_SCHEMA_READER_ENABLED
23076static int
23077xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023078{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023079 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
23080 int depth, nodeType, ret = 0, consumed;
23081 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023082
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023083 vctxt->depth = -1;
23084 ret = xmlTextReaderRead(vctxt->reader);
23085 /*
23086 * Move to the document element.
23087 */
23088 while (ret == 1) {
23089 nodeType = xmlTextReaderNodeType(vctxt->reader);
23090 if (nodeType == XML_ELEMENT_NODE)
23091 goto root_found;
23092 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023093 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023094 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023095
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023096root_found:
23097
23098 do {
23099 depth = xmlTextReaderDepth(vctxt->reader);
23100 nodeType = xmlTextReaderNodeType(vctxt->reader);
23101
23102 if (nodeType == XML_ELEMENT_NODE) {
23103
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023104 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023105 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23106 VERROR_INT("xmlSchemaVReaderWalk",
23107 "calling xmlSchemaValidatorPushElem()");
23108 goto internal_error;
23109 }
23110 ielem = vctxt->inode;
23111 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23112 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23113 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23114 /*
23115 * Is the element empty?
23116 */
23117 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23118 if (ret == -1) {
23119 VERROR_INT("xmlSchemaVReaderWalk",
23120 "calling xmlTextReaderIsEmptyElement()");
23121 goto internal_error;
23122 }
23123 if (ret) {
23124 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23125 }
23126 /*
23127 * Register attributes.
23128 */
23129 vctxt->nbAttrInfos = 0;
23130 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23131 if (ret == -1) {
23132 VERROR_INT("xmlSchemaVReaderWalk",
23133 "calling xmlTextReaderMoveToFirstAttribute()");
23134 goto internal_error;
23135 }
23136 if (ret == 1) {
23137 do {
23138 /*
23139 * VAL TODO: How do we know that the reader works on a
23140 * node tree, to be able to pass a node here?
23141 */
23142 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23143 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23144 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23145 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23146
23147 VERROR_INT("xmlSchemaVReaderWalk",
23148 "calling xmlSchemaValidatorPushAttribute()");
23149 goto internal_error;
23150 }
23151 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23152 if (ret == -1) {
23153 VERROR_INT("xmlSchemaVReaderWalk",
23154 "calling xmlTextReaderMoveToFirstAttribute()");
23155 goto internal_error;
23156 }
23157 } while (ret == 1);
23158 /*
23159 * Back to element position.
23160 */
23161 ret = xmlTextReaderMoveToElement(vctxt->reader);
23162 if (ret == -1) {
23163 VERROR_INT("xmlSchemaVReaderWalk",
23164 "calling xmlTextReaderMoveToElement()");
23165 goto internal_error;
23166 }
23167 }
23168 /*
23169 * Validate the element.
23170 */
23171 ret= xmlSchemaValidateElem(vctxt);
23172 if (ret != 0) {
23173 if (ret == -1) {
23174 VERROR_INT("xmlSchemaVReaderWalk",
23175 "calling xmlSchemaValidateElem()");
23176 goto internal_error;
23177 }
23178 goto exit;
23179 }
23180 if (vctxt->depth == vctxt->skipDepth) {
23181 int curDepth;
23182 /*
23183 * Skip all content.
23184 */
23185 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23186 ret = xmlTextReaderRead(vctxt->reader);
23187 curDepth = xmlTextReaderDepth(vctxt->reader);
23188 while ((ret == 1) && (curDepth != depth)) {
23189 ret = xmlTextReaderRead(vctxt->reader);
23190 curDepth = xmlTextReaderDepth(vctxt->reader);
23191 }
23192 if (ret < 0) {
23193 /*
23194 * VAL TODO: A reader error occured; what to do here?
23195 */
23196 ret = 1;
23197 goto exit;
23198 }
23199 }
23200 goto leave_elem;
23201 }
23202 /*
23203 * READER VAL TODO: Is an END_ELEM really never called
23204 * if the elem is empty?
23205 */
23206 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23207 goto leave_elem;
23208 } else if (nodeType == END_ELEM) {
23209 /*
23210 * Process END of element.
23211 */
23212leave_elem:
23213 ret = xmlSchemaValidatorPopElem(vctxt);
23214 if (ret != 0) {
23215 if (ret < 0) {
23216 VERROR_INT("xmlSchemaVReaderWalk",
23217 "calling xmlSchemaValidatorPopElem()");
23218 goto internal_error;
23219 }
23220 goto exit;
23221 }
23222 if (vctxt->depth >= 0)
23223 ielem = vctxt->inode;
23224 else
23225 ielem = NULL;
23226 } else if ((nodeType == XML_TEXT_NODE) ||
23227 (nodeType == XML_CDATA_SECTION_NODE) ||
23228 (nodeType == WHTSP) ||
23229 (nodeType == SIGN_WHTSP)) {
23230 /*
23231 * Process character content.
23232 */
23233 xmlChar *value;
23234
23235 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23236 nodeType = XML_TEXT_NODE;
23237
23238 value = xmlTextReaderValue(vctxt->reader);
23239 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23240 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23241 if (! consumed)
23242 xmlFree(value);
23243 if (ret == -1) {
23244 VERROR_INT("xmlSchemaVReaderWalk",
23245 "calling xmlSchemaVPushText()");
23246 goto internal_error;
23247 }
23248 } else if ((nodeType == XML_ENTITY_NODE) ||
23249 (nodeType == XML_ENTITY_REF_NODE)) {
23250 /*
23251 * VAL TODO: What to do with entities?
23252 */
23253 TODO
23254 }
23255 /*
23256 * Read next node.
23257 */
23258 ret = xmlTextReaderRead(vctxt->reader);
23259 } while (ret == 1);
23260
23261exit:
23262 return (ret);
23263internal_error:
23264 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023265}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023266#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023267
23268/************************************************************************
23269 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023270 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023271 * *
23272 ************************************************************************/
23273
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023274#ifdef XML_SCHEMA_SAX_ENABLED
23275/*
23276* Process text content.
23277*/
23278static void
23279xmlSchemaSAXHandleText(void *ctx,
23280 const xmlChar * ch,
23281 int len)
23282{
23283 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23284
23285 if (vctxt->depth < 0)
23286 return;
23287 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23288 return;
23289 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23290 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23291 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23292 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23293 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23294 "calling xmlSchemaVPushText()");
23295 vctxt->err = -1;
23296 xmlStopParser(vctxt->parserCtxt);
23297 }
23298}
23299
23300/*
23301* Process CDATA content.
23302*/
23303static void
23304xmlSchemaSAXHandleCDataSection(void *ctx,
23305 const xmlChar * ch,
23306 int len)
23307{
23308 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23309
23310 if (vctxt->depth < 0)
23311 return;
23312 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23313 return;
23314 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23315 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23316 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23317 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23318 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23319 "calling xmlSchemaVPushText()");
23320 vctxt->err = -1;
23321 xmlStopParser(vctxt->parserCtxt);
23322 }
23323}
23324
23325static void
23326xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23327 const xmlChar * name ATTRIBUTE_UNUSED)
23328{
23329 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23330
23331 if (vctxt->depth < 0)
23332 return;
23333 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23334 return;
23335 /* SAX VAL TODO: What to do here? */
23336 TODO
23337}
23338
23339static void
23340xmlSchemaSAXHandleStartElementNs(void *ctx,
23341 const xmlChar * localname,
23342 const xmlChar * prefix ATTRIBUTE_UNUSED,
23343 const xmlChar * URI,
23344 int nb_namespaces,
23345 const xmlChar ** namespaces,
23346 int nb_attributes,
23347 int nb_defaulted ATTRIBUTE_UNUSED,
23348 const xmlChar ** attributes)
23349{
23350 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23351 int ret;
23352 xmlSchemaNodeInfoPtr ielem;
23353 int i, j;
23354
23355 /*
23356 * SAX VAL TODO: What to do with nb_defaulted?
23357 */
23358 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023359 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023360 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023361 vctxt->depth++;
23362 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023363 return;
23364 /*
23365 * Push the element.
23366 */
23367 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23368 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23369 "calling xmlSchemaValidatorPushElem()");
23370 goto internal_error;
23371 }
23372 ielem = vctxt->inode;
23373 ielem->localName = localname;
23374 ielem->nsName = URI;
23375 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23376 /*
23377 * Register namespaces on the elem info.
23378 */
23379 if (nb_namespaces != 0) {
23380 /*
23381 * Although the parser builds its own namespace list,
23382 * we have no access to it, so we'll use an own one.
23383 */
23384 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23385 /*
23386 * Store prefix and namespace name.
23387 */
23388 if (ielem->nsBindings == NULL) {
23389 ielem->nsBindings =
23390 (const xmlChar **) xmlMalloc(10 *
23391 sizeof(const xmlChar *));
23392 if (ielem->nsBindings == NULL) {
23393 xmlSchemaVErrMemory(vctxt,
23394 "allocating namespace bindings for SAX validation",
23395 NULL);
23396 goto internal_error;
23397 }
23398 ielem->nbNsBindings = 0;
23399 ielem->sizeNsBindings = 5;
23400 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23401 ielem->sizeNsBindings *= 2;
23402 ielem->nsBindings =
23403 (const xmlChar **) xmlRealloc(
23404 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023405 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023406 if (ielem->nsBindings == NULL) {
23407 xmlSchemaVErrMemory(vctxt,
23408 "re-allocating namespace bindings for SAX validation",
23409 NULL);
23410 goto internal_error;
23411 }
23412 }
23413
23414 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23415 if (namespaces[j+1][0] == 0) {
23416 /*
23417 * Handle xmlns="".
23418 */
23419 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23420 } else
23421 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23422 namespaces[j+1];
23423 ielem->nbNsBindings++;
23424 }
23425 }
23426 /*
23427 * Register attributes.
23428 * SAX VAL TODO: We are not adding namespace declaration
23429 * attributes yet.
23430 */
23431 if (nb_attributes != 0) {
23432 xmlChar *value;
23433
23434 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23435 /*
23436 * Duplicate the value.
23437 */
23438 value = xmlStrndup(attributes[j+3],
23439 attributes[j+4] - attributes[j+3]);
23440 ret = xmlSchemaValidatorPushAttribute(vctxt,
23441 NULL, attributes[j], attributes[j+2], 0,
23442 value, 1);
23443 if (ret == -1) {
23444 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23445 "calling xmlSchemaValidatorPushAttribute()");
23446 goto internal_error;
23447 }
23448 }
23449 }
23450 /*
23451 * Validate the element.
23452 */
23453 ret = xmlSchemaValidateElem(vctxt);
23454 if (ret != 0) {
23455 if (ret == -1) {
23456 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23457 "calling xmlSchemaValidateElem()");
23458 goto internal_error;
23459 }
23460 goto exit;
23461 }
23462
23463exit:
23464 return;
23465internal_error:
23466 vctxt->err = -1;
23467 xmlStopParser(vctxt->parserCtxt);
23468 return;
23469}
23470
23471static void
23472xmlSchemaSAXHandleEndElementNs(void *ctx,
23473 const xmlChar * localname ATTRIBUTE_UNUSED,
23474 const xmlChar * prefix ATTRIBUTE_UNUSED,
23475 const xmlChar * URI ATTRIBUTE_UNUSED)
23476{
23477 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23478 int res;
23479
23480 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023481 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023482 */
23483 if (vctxt->skipDepth != -1) {
23484 if (vctxt->depth > vctxt->skipDepth) {
23485 vctxt->depth--;
23486 return;
23487 } else
23488 vctxt->skipDepth = -1;
23489 }
23490 /*
23491 * SAX VAL TODO: Just a temporary check.
23492 */
23493 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23494 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23495 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23496 "elem pop mismatch");
23497 }
23498 res = xmlSchemaValidatorPopElem(vctxt);
23499 if (res != 0) {
23500 if (res < 0) {
23501 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23502 "calling xmlSchemaValidatorPopElem()");
23503 goto internal_error;
23504 }
23505 goto exit;
23506 }
23507exit:
23508 return;
23509internal_error:
23510 vctxt->err = -1;
23511 xmlStopParser(vctxt->parserCtxt);
23512 return;
23513}
23514#endif
23515
Daniel Veillard4255d502002-04-16 15:50:10 +000023516/************************************************************************
23517 * *
23518 * Validation interfaces *
23519 * *
23520 ************************************************************************/
23521
23522/**
23523 * xmlSchemaNewValidCtxt:
23524 * @schema: a precompiled XML Schemas
23525 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023526 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023527 *
23528 * Returns the validation context or NULL in case of error
23529 */
23530xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023531xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23532{
Daniel Veillard4255d502002-04-16 15:50:10 +000023533 xmlSchemaValidCtxtPtr ret;
23534
23535 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23536 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023537 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000023538 return (NULL);
23539 }
23540 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023541 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
23542 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000023543 return (ret);
23544}
23545
23546/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023547 * xmlSchemaClearValidCtxt:
23548 * @ctxt: the schema validation context
23549 *
23550 * Free the resources associated to the schema validation context;
23551 * leaves some fields alive intended for reuse of the context.
23552 */
23553static void
23554xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
23555{
23556 if (vctxt == NULL)
23557 return;
23558
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023559 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023560 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023561 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023562#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023563 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000023564#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023565 if (vctxt->value != NULL) {
23566 xmlSchemaFreeValue(vctxt->value);
23567 vctxt->value = NULL;
23568 }
23569 /*
23570 * Augmented IDC information.
23571 */
23572 if (vctxt->aidcs != NULL) {
23573 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
23574 do {
23575 next = cur->next;
23576 xmlFree(cur);
23577 cur = next;
23578 } while (cur != NULL);
23579 vctxt->aidcs = NULL;
23580 }
23581 if (vctxt->idcNodes != NULL) {
23582 int i;
23583 xmlSchemaPSVIIDCNodePtr item;
23584
23585 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023586 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023587 xmlFree(item->keys);
23588 xmlFree(item);
23589 }
23590 xmlFree(vctxt->idcNodes);
23591 vctxt->idcNodes = NULL;
23592 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023593 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023594 * Note that we won't delete the XPath state pool here.
23595 */
23596 if (vctxt->xpathStates != NULL) {
23597 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
23598 vctxt->xpathStates = NULL;
23599 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023600 /*
23601 * Attribute info.
23602 */
23603 if (vctxt->nbAttrInfos != 0) {
23604 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023605 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023606 /*
23607 * Element info.
23608 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023609 if (vctxt->elemInfos != NULL) {
23610 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023611 xmlSchemaNodeInfoPtr ei;
23612
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023613 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023614 ei = vctxt->elemInfos[i];
23615 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023616 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023617 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023618 }
23619 }
23620}
23621
23622/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023623 * xmlSchemaFreeValidCtxt:
23624 * @ctxt: the schema validation context
23625 *
23626 * Free the resources associated to the schema validation context
23627 */
23628void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023629xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
23630{
Daniel Veillard4255d502002-04-16 15:50:10 +000023631 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023632 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000023633 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023634 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023635 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023636 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023637 if (ctxt->idcNodes != NULL) {
23638 int i;
23639 xmlSchemaPSVIIDCNodePtr item;
23640
23641 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023642 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023643 xmlFree(item->keys);
23644 xmlFree(item);
23645 }
23646 xmlFree(ctxt->idcNodes);
23647 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023648 if (ctxt->idcKeys != NULL) {
23649 int i;
23650 for (i = 0; i < ctxt->nbIdcKeys; i++)
23651 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
23652 xmlFree(ctxt->idcKeys);
23653 }
23654
23655 if (ctxt->xpathStates != NULL)
23656 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
23657 if (ctxt->xpathStatePool != NULL)
23658 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
23659
23660 /*
23661 * Augmented IDC information.
23662 */
23663 if (ctxt->aidcs != NULL) {
23664 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
23665 do {
23666 next = cur->next;
23667 xmlFree(cur);
23668 cur = next;
23669 } while (cur != NULL);
23670 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023671 if (ctxt->attrInfos != NULL) {
23672 int i;
23673 xmlSchemaAttrInfoPtr attr;
23674
23675 /* Just a paranoid call to the cleanup. */
23676 if (ctxt->nbAttrInfos != 0)
23677 xmlSchemaClearAttrInfos(ctxt);
23678 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
23679 attr = ctxt->attrInfos[i];
23680 xmlFree(attr);
23681 }
23682 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023683 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023684 if (ctxt->elemInfos != NULL) {
23685 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023686 xmlSchemaNodeInfoPtr ei;
23687
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023688 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023689 ei = ctxt->elemInfos[i];
23690 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023691 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023692 xmlSchemaClearElemInfo(ei);
23693 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000023694 }
23695 xmlFree(ctxt->elemInfos);
23696 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023697 if (ctxt->dict != NULL)
23698 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000023699 xmlFree(ctxt);
23700}
23701
23702/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000023703 * xmlSchemaIsValid:
23704 * @ctxt: the schema validation context
23705 *
23706 * Check if any error was detected during validation.
23707 *
23708 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
23709 * of internal error.
23710 */
23711int
23712xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
23713{
23714 if (ctxt == NULL)
23715 return(-1);
23716 return(ctxt->err == 0);
23717}
23718
23719/**
Daniel Veillard4255d502002-04-16 15:50:10 +000023720 * xmlSchemaSetValidErrors:
23721 * @ctxt: a schema validation context
23722 * @err: the error function
23723 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000023724 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000023725 *
William M. Brack2f2a6632004-08-20 23:09:47 +000023726 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000023727 */
23728void
23729xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023730 xmlSchemaValidityErrorFunc err,
23731 xmlSchemaValidityWarningFunc warn, void *ctx)
23732{
Daniel Veillard4255d502002-04-16 15:50:10 +000023733 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023734 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000023735 ctxt->error = err;
23736 ctxt->warning = warn;
23737 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023738 if (ctxt->pctxt != NULL)
23739 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000023740}
23741
23742/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000023743 * xmlSchemaSetValidStructuredErrors:
23744 * @ctxt: a schema validation context
23745 * @serror: the structured error function
23746 * @ctx: the functions context
23747 *
23748 * Set the structured error callback
23749 */
23750void
23751xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
23752 xmlStructuredErrorFunc serror, void *ctx)
23753{
23754 if (ctxt == NULL)
23755 return;
23756 ctxt->serror = serror;
23757 ctxt->error = NULL;
23758 ctxt->warning = NULL;
23759 ctxt->userData = ctx;
23760}
23761
23762/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000023763 * xmlSchemaGetValidErrors:
23764 * @ctxt: a XML-Schema validation context
23765 * @err: the error function result
23766 * @warn: the warning function result
23767 * @ctx: the functions context result
23768 *
23769 * Get the error and warning callback informations
23770 *
23771 * Returns -1 in case of error and 0 otherwise
23772 */
23773int
23774xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
23775 xmlSchemaValidityErrorFunc * err,
23776 xmlSchemaValidityWarningFunc * warn, void **ctx)
23777{
23778 if (ctxt == NULL)
23779 return (-1);
23780 if (err != NULL)
23781 *err = ctxt->error;
23782 if (warn != NULL)
23783 *warn = ctxt->warning;
23784 if (ctx != NULL)
23785 *ctx = ctxt->userData;
23786 return (0);
23787}
23788
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023789
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023790/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023791 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023792 * @ctxt: a schema validation context
23793 * @options: a combination of xmlSchemaValidOption
23794 *
23795 * Sets the options to be used during the validation.
23796 *
23797 * Returns 0 in case of success, -1 in case of an
23798 * API error.
23799 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023800int
23801xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
23802 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023803
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023804{
23805 int i;
23806
23807 if (ctxt == NULL)
23808 return (-1);
23809 /*
23810 * WARNING: Change the start value if adding to the
23811 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023812 * TODO: Is there an other, more easy to maintain,
23813 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023814 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023815 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023816 if (options & 1<<i)
23817 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023818 }
23819 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023820 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023821}
23822
23823/**
Daniel Veillard6927b102004-10-27 17:29:04 +000023824 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023825 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023826 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023827 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023828 *
William M. Brack21e4ef22005-01-02 09:53:13 +000023829 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023830 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023831int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023832xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023833
23834{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023835 if (ctxt == NULL)
23836 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023837 else
23838 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023839}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023840
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023841static int
23842xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
23843{
23844 xmlAttrPtr attr;
23845 int ret = 0;
23846 xmlSchemaNodeInfoPtr ielem = NULL;
23847 xmlNodePtr node, valRoot;
23848 const xmlChar *nsName;
23849
23850 /* DOC VAL TODO: Move this to the start function. */
23851 valRoot = xmlDocGetRootElement(vctxt->doc);
23852 if (valRoot == NULL) {
23853 /* VAL TODO: Error code? */
23854 VERROR(1, NULL, "The document has no document element");
23855 return (1);
23856 }
23857 vctxt->depth = -1;
23858 vctxt->validationRoot = valRoot;
23859 node = valRoot;
23860 while (node != NULL) {
23861 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23862 goto next_sibling;
23863 if (node->type == XML_ELEMENT_NODE) {
23864
23865 /*
23866 * Init the node-info.
23867 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023868 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023869 if (xmlSchemaValidatorPushElem(vctxt) == -1)
23870 goto internal_error;
23871 ielem = vctxt->inode;
23872 ielem->node = node;
23873 ielem->localName = node->name;
23874 if (node->ns != NULL)
23875 ielem->nsName = node->ns->href;
23876 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23877 /*
23878 * Register attributes.
23879 * DOC VAL TODO: We do not register namespace declaration
23880 * attributes yet.
23881 */
23882 vctxt->nbAttrInfos = 0;
23883 if (node->properties != NULL) {
23884 attr = node->properties;
23885 do {
23886 if (attr->ns != NULL)
23887 nsName = attr->ns->href;
23888 else
23889 nsName = NULL;
23890 ret = xmlSchemaValidatorPushAttribute(vctxt,
23891 (xmlNodePtr) attr,
23892 attr->name, nsName, 0,
23893 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
23894 if (ret == -1) {
23895 VERROR_INT("xmlSchemaDocWalk",
23896 "calling xmlSchemaValidatorPushAttribute()");
23897 goto internal_error;
23898 }
23899 attr = attr->next;
23900 } while (attr);
23901 }
23902 /*
23903 * Validate the element.
23904 */
23905 ret = xmlSchemaValidateElem(vctxt);
23906 if (ret != 0) {
23907 if (ret == -1) {
23908 VERROR_INT("xmlSchemaDocWalk",
23909 "calling xmlSchemaValidateElem()");
23910 goto internal_error;
23911 }
23912 /*
23913 * Don't stop validation; just skip the content
23914 * of this element.
23915 */
23916 goto leave_node;
23917 }
23918 if ((vctxt->skipDepth != -1) &&
23919 (vctxt->depth >= vctxt->skipDepth))
23920 goto leave_node;
23921 } else if ((node->type == XML_TEXT_NODE) ||
23922 (node->type == XML_CDATA_SECTION_NODE)) {
23923 /*
23924 * Process character content.
23925 */
23926 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23927 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23928 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
23929 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
23930 if (ret < 0) {
23931 VERROR_INT("xmlSchemaVDocWalk",
23932 "calling xmlSchemaVPushText()");
23933 goto internal_error;
23934 }
23935 /*
23936 * DOC VAL TODO: Should we skip further validation of the
23937 * element content here?
23938 */
23939 } else if ((node->type == XML_ENTITY_NODE) ||
23940 (node->type == XML_ENTITY_REF_NODE)) {
23941 /*
23942 * DOC VAL TODO: What to do with entities?
23943 */
23944 TODO
23945 } else {
23946 goto leave_node;
23947 /*
23948 * DOC VAL TODO: XInclude nodes, etc.
23949 */
23950 }
23951 /*
23952 * Walk the doc.
23953 */
23954 if (node->children != NULL) {
23955 node = node->children;
23956 continue;
23957 }
23958leave_node:
23959 if (node->type == XML_ELEMENT_NODE) {
23960 /*
23961 * Leaving the scope of an element.
23962 */
23963 if (node != vctxt->inode->node) {
23964 VERROR_INT("xmlSchemaVDocWalk",
23965 "element position mismatch");
23966 goto internal_error;
23967 }
23968 ret = xmlSchemaValidatorPopElem(vctxt);
23969 if (ret != 0) {
23970 if (ret < 0) {
23971 VERROR_INT("xmlSchemaVDocWalk",
23972 "calling xmlSchemaValidatorPopElem()");
23973 goto internal_error;
23974 }
23975 }
23976 if (node == valRoot)
23977 goto exit;
23978 }
23979next_sibling:
23980 if (node->next != NULL)
23981 node = node->next;
23982 else {
23983 node = node->parent;
23984 goto leave_node;
23985 }
23986 }
23987
23988exit:
23989 return (ret);
23990internal_error:
23991 return (-1);
23992}
23993
23994static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000023995xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023996 /*
23997 * Some initialization.
23998 */
23999 vctxt->err = 0;
24000 vctxt->nberrors = 0;
24001 vctxt->depth = -1;
24002 vctxt->skipDepth = -1;
24003 /*
24004 * Create a schema + parser if necessary.
24005 */
24006 if (vctxt->schema == NULL) {
24007
24008 if ((vctxt->pctxt == NULL) &&
24009 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24010 return (-1);
24011
24012 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
24013 if (vctxt->schema == NULL) {
24014 VERROR_INT("xmlSchemaVStartValidation",
24015 "creating a schema");
24016 return (-1);
24017 }
24018 vctxt->xsiAssemble = 1;
24019 } else
24020 vctxt->xsiAssemble = 0;
24021 /*
24022 * Augment the IDC definitions.
24023 */
24024 if (vctxt->schema->idcDef != NULL) {
24025 xmlHashScan(vctxt->schema->idcDef,
24026 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
24027 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000024028 return(0);
24029}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024030
Daniel Veillardf10ae122005-07-10 19:03:16 +000024031static void
24032xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024033 if (vctxt->xsiAssemble) {
24034 if (vctxt->schema != NULL) {
24035 xmlSchemaFree(vctxt->schema);
24036 vctxt->schema = NULL;
24037 }
24038 }
24039 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024040}
24041
24042static int
24043xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
24044{
24045 int ret = 0;
24046
24047 if (xmlSchemaPreRun(vctxt) < 0)
24048 return(-1);
24049
24050 if (vctxt->doc != NULL) {
24051 /*
24052 * Tree validation.
24053 */
24054 ret = xmlSchemaVDocWalk(vctxt);
24055#ifdef LIBXML_READER_ENABLED
24056 } else if (vctxt->reader != NULL) {
24057 /*
24058 * XML Reader validation.
24059 */
24060#ifdef XML_SCHEMA_READER_ENABLED
24061 ret = xmlSchemaVReaderWalk(vctxt);
24062#endif
24063#endif
24064 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
24065 /*
24066 * SAX validation.
24067 */
24068 ret = xmlParseDocument(vctxt->parserCtxt);
24069 } else {
24070 VERROR_INT("xmlSchemaVStartValidation",
24071 "no instance to validate");
24072 ret = -1;
24073 }
24074
24075 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024076 if (ret == 0)
24077 ret = vctxt->err;
24078 return (ret);
24079}
24080
24081/**
24082 * xmlSchemaValidateOneElement:
24083 * @ctxt: a schema validation context
24084 * @elem: an element node
24085 *
24086 * Validate a branch of a tree, starting with the given @elem.
24087 *
24088 * Returns 0 if the element and its subtree is valid, a positive error
24089 * code number otherwise and -1 in case of an internal or API error.
24090 */
24091int
24092xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24093{
24094 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24095 return (-1);
24096
24097 if (ctxt->schema == NULL)
24098 return (-1);
24099
24100 ctxt->doc = elem->doc;
24101 ctxt->node = elem;
24102 ctxt->validationRoot = elem;
24103 return(xmlSchemaVStart(ctxt));
24104}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024105
Daniel Veillard259f0df2004-08-18 09:13:18 +000024106/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024107 * xmlSchemaValidateDoc:
24108 * @ctxt: a schema validation context
24109 * @doc: a parsed document tree
24110 *
24111 * Validate a document tree in memory.
24112 *
24113 * Returns 0 if the document is schemas valid, a positive error code
24114 * number otherwise and -1 in case of internal or API error.
24115 */
24116int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024117xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24118{
Daniel Veillard4255d502002-04-16 15:50:10 +000024119 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024120 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024121
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024122 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024123 ctxt->node = xmlDocGetRootElement(doc);
24124 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024125 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024126 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24127 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024128 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024129 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024130 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024131 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024132 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024133}
24134
Daniel Veillardcdc82732005-07-08 15:04:06 +000024135
24136/************************************************************************
24137 * *
24138 * Function and data for SAX streaming API *
24139 * *
24140 ************************************************************************/
24141typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24142typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24143
24144struct _xmlSchemaSplitSAXData {
24145 xmlSAXHandlerPtr user_sax;
24146 void *user_data;
24147 xmlSchemaValidCtxtPtr ctxt;
24148 xmlSAXHandlerPtr schemas_sax;
24149};
24150
Daniel Veillard971771e2005-07-09 17:32:57 +000024151#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24152
24153struct _xmlSchemaSAXPlug {
24154 unsigned int magic;
24155
24156 /* the original callbacks informations */
24157 xmlSAXHandlerPtr *user_sax_ptr;
24158 xmlSAXHandlerPtr user_sax;
24159 void **user_data_ptr;
24160 void *user_data;
24161
24162 /* the block plugged back and validation informations */
24163 xmlSAXHandler schemas_sax;
24164 xmlSchemaValidCtxtPtr ctxt;
24165};
24166
Daniel Veillardcdc82732005-07-08 15:04:06 +000024167/* All those functions just bounces to the user provided SAX handlers */
24168static void
24169internalSubsetSplit(void *ctx, const xmlChar *name,
24170 const xmlChar *ExternalID, const xmlChar *SystemID)
24171{
Daniel Veillard971771e2005-07-09 17:32:57 +000024172 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024173 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24174 (ctxt->user_sax->internalSubset != NULL))
24175 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24176 SystemID);
24177}
24178
24179static int
24180isStandaloneSplit(void *ctx)
24181{
Daniel Veillard971771e2005-07-09 17:32:57 +000024182 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024183 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24184 (ctxt->user_sax->isStandalone != NULL))
24185 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24186 return(0);
24187}
24188
24189static int
24190hasInternalSubsetSplit(void *ctx)
24191{
Daniel Veillard971771e2005-07-09 17:32:57 +000024192 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024193 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24194 (ctxt->user_sax->hasInternalSubset != NULL))
24195 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24196 return(0);
24197}
24198
24199static int
24200hasExternalSubsetSplit(void *ctx)
24201{
Daniel Veillard971771e2005-07-09 17:32:57 +000024202 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024203 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24204 (ctxt->user_sax->hasExternalSubset != NULL))
24205 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24206 return(0);
24207}
24208
24209static void
24210externalSubsetSplit(void *ctx, const xmlChar *name,
24211 const xmlChar *ExternalID, const xmlChar *SystemID)
24212{
Daniel Veillard971771e2005-07-09 17:32:57 +000024213 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024214 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24215 (ctxt->user_sax->internalSubset != NULL))
24216 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24217 SystemID);
24218}
24219
24220static xmlParserInputPtr
24221resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24222{
Daniel Veillard971771e2005-07-09 17:32:57 +000024223 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024224 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24225 (ctxt->user_sax->resolveEntity != NULL))
24226 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24227 systemId));
24228 return(NULL);
24229}
24230
24231static xmlEntityPtr
24232getEntitySplit(void *ctx, const xmlChar *name)
24233{
Daniel Veillard971771e2005-07-09 17:32:57 +000024234 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024235 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24236 (ctxt->user_sax->getEntity != NULL))
24237 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24238 return(NULL);
24239}
24240
24241static xmlEntityPtr
24242getParameterEntitySplit(void *ctx, const xmlChar *name)
24243{
Daniel Veillard971771e2005-07-09 17:32:57 +000024244 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024245 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24246 (ctxt->user_sax->getParameterEntity != NULL))
24247 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24248 return(NULL);
24249}
24250
24251
24252static void
24253entityDeclSplit(void *ctx, const xmlChar *name, int type,
24254 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24255{
Daniel Veillard971771e2005-07-09 17:32:57 +000024256 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024257 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24258 (ctxt->user_sax->entityDecl != NULL))
24259 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24260 systemId, content);
24261}
24262
24263static void
24264attributeDeclSplit(void *ctx, const xmlChar * elem,
24265 const xmlChar * name, int type, int def,
24266 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24267{
Daniel Veillard971771e2005-07-09 17:32:57 +000024268 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024269 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24270 (ctxt->user_sax->attributeDecl != NULL)) {
24271 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24272 def, defaultValue, tree);
24273 } else {
24274 xmlFreeEnumeration(tree);
24275 }
24276}
24277
24278static void
24279elementDeclSplit(void *ctx, const xmlChar *name, int type,
24280 xmlElementContentPtr content)
24281{
Daniel Veillard971771e2005-07-09 17:32:57 +000024282 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024283 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24284 (ctxt->user_sax->elementDecl != NULL))
24285 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24286}
24287
24288static void
24289notationDeclSplit(void *ctx, const xmlChar *name,
24290 const xmlChar *publicId, const xmlChar *systemId)
24291{
Daniel Veillard971771e2005-07-09 17:32:57 +000024292 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024293 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24294 (ctxt->user_sax->notationDecl != NULL))
24295 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24296 systemId);
24297}
24298
24299static void
24300unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24301 const xmlChar *publicId, const xmlChar *systemId,
24302 const xmlChar *notationName)
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->unparsedEntityDecl != NULL))
24307 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24308 systemId, notationName);
24309}
24310
24311static void
24312setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24313{
Daniel Veillard971771e2005-07-09 17:32:57 +000024314 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024315 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24316 (ctxt->user_sax->setDocumentLocator != NULL))
24317 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24318}
24319
24320static void
24321startDocumentSplit(void *ctx)
24322{
Daniel Veillard971771e2005-07-09 17:32:57 +000024323 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024324 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24325 (ctxt->user_sax->startDocument != NULL))
24326 ctxt->user_sax->startDocument(ctxt->user_data);
24327}
24328
24329static void
24330endDocumentSplit(void *ctx)
24331{
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->endDocument != NULL))
24335 ctxt->user_sax->endDocument(ctxt->user_data);
24336}
24337
24338static void
24339processingInstructionSplit(void *ctx, const xmlChar *target,
24340 const xmlChar *data)
24341{
Daniel Veillard971771e2005-07-09 17:32:57 +000024342 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024343 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24344 (ctxt->user_sax->processingInstruction != NULL))
24345 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24346}
24347
24348static void
24349commentSplit(void *ctx, const xmlChar *value)
24350{
Daniel Veillard971771e2005-07-09 17:32:57 +000024351 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024352 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24353 (ctxt->user_sax->comment != NULL))
24354 ctxt->user_sax->comment(ctxt->user_data, value);
24355}
24356
24357/*
24358 * Varargs error callbacks to the user application, harder ...
24359 */
24360
24361static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024362warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024363 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024364 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24365 (ctxt->user_sax->warning != NULL)) {
24366 TODO
24367 }
24368}
24369static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024370errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024371 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024372 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24373 (ctxt->user_sax->error != NULL)) {
24374 TODO
24375 }
24376}
24377static void
Daniel Veillardafc05b62005-07-17 06:11:19 +000024378fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024379 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024380 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24381 (ctxt->user_sax->fatalError != NULL)) {
24382 TODO
24383 }
24384}
24385
24386/*
24387 * Those are function where both the user handler and the schemas handler
24388 * need to be called.
24389 */
24390static void
24391charactersSplit(void *ctx, const xmlChar *ch, int len)
24392{
Daniel Veillard971771e2005-07-09 17:32:57 +000024393 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024394 if (ctxt == NULL)
24395 return;
24396 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24397 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24398 if (ctxt->ctxt != NULL)
24399 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24400}
24401
24402static void
24403ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24404{
Daniel Veillard971771e2005-07-09 17:32:57 +000024405 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024406 if (ctxt == NULL)
24407 return;
24408 if ((ctxt->user_sax != NULL) &&
24409 (ctxt->user_sax->ignorableWhitespace != NULL))
24410 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24411 if (ctxt->ctxt != NULL)
24412 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24413}
24414
24415static void
24416cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24417{
Daniel Veillard971771e2005-07-09 17:32:57 +000024418 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024419 if (ctxt == NULL)
24420 return;
24421 if ((ctxt->user_sax != NULL) &&
24422 (ctxt->user_sax->ignorableWhitespace != NULL))
24423 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24424 if (ctxt->ctxt != NULL)
24425 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24426}
24427
24428static void
24429referenceSplit(void *ctx, const xmlChar *name)
24430{
Daniel Veillard971771e2005-07-09 17:32:57 +000024431 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024432 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24433 (ctxt->user_sax->reference != NULL))
24434 ctxt->user_sax->reference(ctxt->user_data, name);
24435 if (ctxt->ctxt != NULL)
24436 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24437}
24438
24439static void
24440startElementNsSplit(void *ctx, const xmlChar * localname,
24441 const xmlChar * prefix, const xmlChar * URI,
24442 int nb_namespaces, const xmlChar ** namespaces,
24443 int nb_attributes, int nb_defaulted,
24444 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024445 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024446 if (ctxt == NULL)
24447 return;
24448 if ((ctxt->user_sax != NULL) &&
24449 (ctxt->user_sax->startElementNs != NULL))
24450 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24451 URI, nb_namespaces, namespaces,
24452 nb_attributes, nb_defaulted,
24453 attributes);
24454 if (ctxt->ctxt != NULL)
24455 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24456 URI, nb_namespaces, namespaces,
24457 nb_attributes, nb_defaulted,
24458 attributes);
24459}
24460
24461static void
24462endElementNsSplit(void *ctx, const xmlChar * localname,
24463 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024464 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024465 if (ctxt == NULL)
24466 return;
24467 if ((ctxt->user_sax != NULL) &&
24468 (ctxt->user_sax->endElementNs != NULL))
24469 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24470 if (ctxt->ctxt != NULL)
24471 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24472}
24473
Daniel Veillard4255d502002-04-16 15:50:10 +000024474/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024475 * xmlSchemaSAXPlug:
24476 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024477 * @sax: a pointer to the original xmlSAXHandlerPtr
24478 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024479 *
24480 * Plug a SAX based validation layer in a SAX parsing event flow.
24481 * The original @saxptr and @dataptr data are replaced by new pointers
24482 * but the calls to the original will be maintained.
24483 *
24484 * Returns a pointer to a data structure needed to unplug the validation layer
24485 * or NULL in case of errors.
24486 */
24487xmlSchemaSAXPlugPtr
24488xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24489 xmlSAXHandlerPtr *sax, void **user_data)
24490{
24491 xmlSchemaSAXPlugPtr ret;
24492 xmlSAXHandlerPtr old_sax;
24493
24494 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24495 return(NULL);
24496
24497 /*
24498 * We only allow to plug into SAX2 event streams
24499 */
24500 old_sax = *sax;
24501 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24502 return(NULL);
24503 if ((old_sax != NULL) &&
24504 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24505 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24506 return(NULL);
24507
24508 /*
24509 * everything seems right allocate the local data needed for that layer
24510 */
24511 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24512 if (ret == NULL) {
24513 return(NULL);
24514 }
24515 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24516 ret->magic = XML_SAX_PLUG_MAGIC;
24517 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24518 ret->ctxt = ctxt;
24519 ret->user_sax_ptr = sax;
24520 ret->user_sax = old_sax;
24521 if (old_sax == NULL) {
24522 /*
24523 * go direct, no need for the split block and functions.
24524 */
24525 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
24526 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
24527 /*
24528 * Note that we use the same text-function for both, to prevent
24529 * the parser from testing for ignorable whitespace.
24530 */
24531 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
24532 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
24533
24534 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
24535 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
24536
24537 ret->user_data = ctxt;
24538 *user_data = ctxt;
24539 } else {
24540 /*
24541 * for each callback unused by Schemas initialize it to the Split
24542 * routine only if non NULL in the user block, this can speed up
24543 * things at the SAX level.
24544 */
24545 if (old_sax->internalSubset != NULL)
24546 ret->schemas_sax.internalSubset = internalSubsetSplit;
24547 if (old_sax->isStandalone != NULL)
24548 ret->schemas_sax.isStandalone = isStandaloneSplit;
24549 if (old_sax->hasInternalSubset != NULL)
24550 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
24551 if (old_sax->hasExternalSubset != NULL)
24552 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
24553 if (old_sax->resolveEntity != NULL)
24554 ret->schemas_sax.resolveEntity = resolveEntitySplit;
24555 if (old_sax->getEntity != NULL)
24556 ret->schemas_sax.getEntity = getEntitySplit;
24557 if (old_sax->entityDecl != NULL)
24558 ret->schemas_sax.entityDecl = entityDeclSplit;
24559 if (old_sax->notationDecl != NULL)
24560 ret->schemas_sax.notationDecl = notationDeclSplit;
24561 if (old_sax->attributeDecl != NULL)
24562 ret->schemas_sax.attributeDecl = attributeDeclSplit;
24563 if (old_sax->elementDecl != NULL)
24564 ret->schemas_sax.elementDecl = elementDeclSplit;
24565 if (old_sax->unparsedEntityDecl != NULL)
24566 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
24567 if (old_sax->setDocumentLocator != NULL)
24568 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
24569 if (old_sax->startDocument != NULL)
24570 ret->schemas_sax.startDocument = startDocumentSplit;
24571 if (old_sax->endDocument != NULL)
24572 ret->schemas_sax.endDocument = endDocumentSplit;
24573 if (old_sax->processingInstruction != NULL)
24574 ret->schemas_sax.processingInstruction = processingInstructionSplit;
24575 if (old_sax->comment != NULL)
24576 ret->schemas_sax.comment = commentSplit;
24577 if (old_sax->warning != NULL)
24578 ret->schemas_sax.warning = warningSplit;
24579 if (old_sax->error != NULL)
24580 ret->schemas_sax.error = errorSplit;
24581 if (old_sax->fatalError != NULL)
24582 ret->schemas_sax.fatalError = fatalErrorSplit;
24583 if (old_sax->getParameterEntity != NULL)
24584 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
24585 if (old_sax->externalSubset != NULL)
24586 ret->schemas_sax.externalSubset = externalSubsetSplit;
24587
24588 /*
24589 * the 6 schemas callback have to go to the splitter functions
24590 * Note that we use the same text-function for ignorableWhitespace
24591 * if possible, to prevent the parser from testing for ignorable
24592 * whitespace.
24593 */
24594 ret->schemas_sax.characters = charactersSplit;
24595 if ((old_sax->ignorableWhitespace != NULL) &&
24596 (old_sax->ignorableWhitespace != old_sax->characters))
24597 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
24598 else
24599 ret->schemas_sax.ignorableWhitespace = charactersSplit;
24600 ret->schemas_sax.cdataBlock = cdataBlockSplit;
24601 ret->schemas_sax.reference = referenceSplit;
24602 ret->schemas_sax.startElementNs = startElementNsSplit;
24603 ret->schemas_sax.endElementNs = endElementNsSplit;
24604
24605 ret->user_data_ptr = user_data;
24606 ret->user_data = *user_data;
24607 *user_data = ret;
24608 }
24609
24610 /*
24611 * plug the pointers back.
24612 */
24613 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024614 ctxt->sax = *sax;
24615 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24616 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024617 return(ret);
24618}
24619
24620/**
24621 * xmlSchemaSAXUnplug:
24622 * @plug: a data structure returned by xmlSchemaSAXPlug
24623 *
24624 * Unplug a SAX based validation layer in a SAX parsing event flow.
24625 * The original pointers used in the call are restored.
24626 *
24627 * Returns 0 in case of success and -1 in case of failure.
24628 */
24629int
24630xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
24631{
24632 xmlSAXHandlerPtr *sax;
24633 void **user_data;
24634
24635 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
24636 return(-1);
24637 plug->magic = 0;
24638
Daniel Veillardf10ae122005-07-10 19:03:16 +000024639 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000024640 /* restore the data */
24641 sax = plug->user_sax_ptr;
24642 *sax = plug->user_sax;
24643 if (plug->user_sax != NULL) {
24644 user_data = plug->user_data_ptr;
24645 *user_data = plug->user_data;
24646 }
24647
24648 /* free and return */
24649 xmlFree(plug);
24650 return(0);
24651}
24652
24653/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024654 * xmlSchemaValidateStream:
24655 * @ctxt: a schema validation context
24656 * @input: the input to use for reading the data
24657 * @enc: an optional encoding information
24658 * @sax: a SAX handler for the resulting events
24659 * @user_data: the context to provide to the SAX handler.
24660 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000024661 * Validate an input based on a flow of SAX event from the parser
24662 * and forward the events to the @sax handler with the provided @user_data
24663 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000024664 *
24665 * Returns 0 if the document is schemas valid, a positive error code
24666 * number otherwise and -1 in case of internal or API error.
24667 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024668int
Daniel Veillard4255d502002-04-16 15:50:10 +000024669xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024670 xmlParserInputBufferPtr input, xmlCharEncoding enc,
24671 xmlSAXHandlerPtr sax, void *user_data)
24672{
Daniel Veillard971771e2005-07-09 17:32:57 +000024673 xmlSchemaSAXPlugPtr plug = NULL;
24674 xmlSAXHandlerPtr old_sax = NULL;
24675 xmlParserCtxtPtr pctxt = NULL;
24676 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024677 int ret;
24678
Daniel Veillard4255d502002-04-16 15:50:10 +000024679 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024680 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000024681
Daniel Veillardcdc82732005-07-08 15:04:06 +000024682 /*
24683 * prepare the parser
24684 */
24685 pctxt = xmlNewParserCtxt();
24686 if (pctxt == NULL)
24687 return (-1);
24688 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000024689 pctxt->sax = sax;
24690 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024691#if 0
24692 if (options)
24693 xmlCtxtUseOptions(pctxt, options);
24694#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000024695 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024696
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000024697 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024698 if (inputStream == NULL) {
24699 ret = -1;
24700 goto done;
24701 }
24702 inputPush(pctxt, inputStream);
24703 ctxt->parserCtxt = pctxt;
24704 ctxt->input = input;
24705
24706 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000024707 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000024708 */
Daniel Veillard971771e2005-07-09 17:32:57 +000024709 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
24710 if (plug == NULL) {
24711 ret = -1;
24712 goto done;
24713 }
24714 ctxt->input = input;
24715 ctxt->enc = enc;
24716 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024717 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
24718 ret = xmlSchemaVStart(ctxt);
24719
24720 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
24721 ret = ctxt->parserCtxt->errNo;
24722 if (ret == 0)
24723 ret = 1;
24724 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024725
24726done:
Daniel Veillard971771e2005-07-09 17:32:57 +000024727 ctxt->parserCtxt = NULL;
24728 ctxt->sax = NULL;
24729 ctxt->input = NULL;
24730 if (plug != NULL) {
24731 xmlSchemaSAXUnplug(plug);
24732 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024733 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000024734 if (pctxt != NULL) {
24735 pctxt->sax = old_sax;
24736 xmlFreeParserCtxt(pctxt);
24737 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000024738 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000024739}
24740
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024741/**
24742 * xmlSchemaValidateFile:
24743 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000024744 * @filename: the URI of the instance
24745 * @options: a future set of options, currently unused
24746 *
24747 * Do a schemas validation of the given resource, it will use the
24748 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024749 *
24750 * Returns 0 if the document is valid, a positive error code
24751 * number otherwise and -1 in case of an internal or API error.
24752 */
24753int
24754xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024755 const char * filename,
24756 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024757{
Daniel Veillard81562d22005-06-15 13:27:56 +000024758#ifdef XML_SCHEMA_SAX_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024759 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024760 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024761
24762 if ((ctxt == NULL) || (filename == NULL))
24763 return (-1);
24764
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024765 input = xmlParserInputBufferCreateFilename(filename,
24766 XML_CHAR_ENCODING_NONE);
24767 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024768 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000024769 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
24770 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024771 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000024772#else
24773 return (-1);
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000024774#endif /* XML_SCHEMA_SAX_ENABLED */
Daniel Veillard81562d22005-06-15 13:27:56 +000024775}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024776
Daniel Veillard5d4644e2005-04-01 13:11:58 +000024777#define bottom_xmlschemas
24778#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000024779#endif /* LIBXML_SCHEMAS_ENABLED */